C# List<object> 无法使用 List<T> 的扩展方法

C# List<object> unable to use extension method of List<T>

我有一个包含不同种类对象的列表,有时这些对象有自己的列表。因此,为了获得列表 AND 子项的 OfType<>(如果适用),我正在创建一个递归函数。但是,我似乎无法使用 List<object>

的扩展方法
        public static List<T2> OfTypeRecursive<T1, T2>(this List<T1> l) where T2 : Type
        {
            var retList = l.OfType<T2>().ToList();

            foreach (var v in l)
                if(v.GetType() == typeof(loopLoopClass))
                    retList.AddRange(((loopLoopClass)(object)v).loopBody.OfTypeRecursive<T2>());

            return retList;
        }

我收到这个错误

'List<object>' does not contain a definition for 'OfTypeRecursive' and no extension method 'OfTypeRecursive' accepting a first argument of type List<object> could be found (are you missing a directive or assembly reference?)

但是,如果我将 this List<T1> l 更改为 this List<object> l,扩展方法就会起作用。我真的很感激任何帮助。谢谢

编辑:我正在使用 .net 核心

查看 this post 上的答案。

下面是为 generic List 定义扩展方法的示例:

using System;
using System.Collections.Generic;

namespace ExtensionMethodTester
{
  public class Program
  {
      public static void Main(string[] args)
      {
          List<string> myList = new List<string>();
          myList.MyTestMethod();
      }
  }

  public static class MyExtensions 
  {
    public static void MyTestMethod<T>(this List<T> list)
    {
         Console.WriteLine("Extension method called");
    }
  }
}

我不确定我明白你想要什么,但我会试一试。

首先,你可以去掉第二个泛型参数,直接用Type代替,然后你需要对List<object>做扩展,而不是List<T>,这将保证编译-时间安全

public static List<Type> OfTypeRecursive<T>(this List<object> list)
{
    var retList = list.OfType<Type>().ToList();

    foreach (var v in list)
        if (v.GetType() == typeof(loopLoopClass))
            retList.AddRange(((loopLoopClass)v).loopBody.OfTypeRecursive<Type>());

    return retList;
}

因为 List<object> != List<T> 它不会像你期望的那样工作。 Covariance and contravariance 是可能有助于您理解这一点的主题。

问题是你对

的定义
public List<object> loopLoopBody

正如错误消息告诉您的那样,对象没有方法

OfTypeRecursive

所以看起来您是在列表项上调用方法,而不是在列表上。 您应该考虑使用类型 T1 和 T2 进行转换,而不是 "loopLoopClass" 和 "object"。也许这可以解决您的问题。

I have a List containing different kinds of objects and sometimes those objects have a list of their own.

此关系需要编码,它将驱动您的类型约束方法。

假设您可以控制具体对象的实现,编码可能如下所示:

public interface INestedList
{
    List<object> InnerList { get; }
}

public class ContainsNestedList : INestedList
{
    public List<object> InnerList { get; }

    public string Name { get; }

    public ContainsNestedList(string name, List<object> innerList)
    {
        Name = name;
        InnerList = innerList;
    }

    public override string ToString()
    {
        return Name;
    }
}

注意:ContainsNestedListName 属性 仅用于视觉识别目的。

如果您无法控制具体的对象类型,仍然应该有某种现有逻辑可以为您提供这种 T1 - T2 关系,否则问题的前提撑不住了。

当您在代码中执行 foreach (var v in l) 时,因为 l 是一个 List<T1>v 也是一个 T1。此外,检查 v 的类型是 loopLoopClass 的类型意味着 T1object(非约束类型)或 loopLoopClass,后者被翻译成 where T1 : loopLoopClass 的约束。

鉴于你之后做了loopBody.OfTypeRecursive<T2>(),根据评论说loopBodyList<object>,现在T1被确定为object.

这将引导我们进入以下代码路径:

public static class ListExtensions
{
    public static List<object> OfTypeRecursive<T>(this List<object> source)
        where T : INestedList
    {
        var itemsToDigInto = source.OfType<T>().ToList();
        var output = source.Except(itemsToDigInto.Cast<object>()).ToList();

        foreach (T item in itemsToDigInto)
        {
            Console.WriteLine($"Extracting from InnerList of {item}");

            output.AddRange(item.InnerList.OfTypeRecursive<T>());

            Console.WriteLine($"Finished processing for {item}");
        }

        return output;
    }
}

public class Program
{
    public static void Main()
    {
        var x = 2;
        var y = 4.3m;
        var z = "sf";
        var p = new ContainsNestedList("p", new List<object> { x, y });
        var q = new ContainsNestedList("q", new List<object> { z, p });
        var r = new ContainsNestedList("r", new List<object> { x, y, p, q });

        var source = new List<object> { x, y, z, q, p, r };

        var result = source.OfTypeRecursive<ContainsNestedList>();

        result.ForEach(i => Console.WriteLine("{0}", i));

        Console.ReadKey();
    }
}

编辑:更新以说明以下前提

you have a list of arbitrary objects. Some of these objects are of type ClassA. Some of the other objects are of some other specific class, say ClassB, which is defined as having an inner list of objects, some of which might also be ClassA or ClassB in type.

public static class ListExtensions
{
    public static List<T> OfTypeRecursive<T, TU>(this List<object> source)
        where TU : INestedList
    {
        var output = source.OfType<T>().ToList();
        var itemsToDigInto = source.OfType<TU>();

        foreach (TU item in itemsToDigInto)
        {
            Console.WriteLine($"Extracting from InnerList of {item}");

            output.AddRange(item.InnerList.OfTypeRecursive<T, TU>());

            Console.WriteLine($"Finished processing for {item}");
        }

        return output;
    }
}