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

时间:2017-08-08 05:01:29

标签: c# generics recursion extension-methods

我有一个包含不同种类对象的List,有时这些对象有自己的列表。因此,为了获得列表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核心

4 个答案:

答案 0 :(得分:1)

我不确定我理解你想要什么,但我会尝试一下。

首先,您可以删除第二个通用参数并直接将其替换为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是可以帮助您理解这一点的主题。

答案 1 :(得分:1)

  

我有一个包含不同类型对象的List,有时这些对象有自己的列表。

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

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

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;
    }
}

注意:Name的{​​{1}}属性仅用于视觉识别目的。

如果您无法控制具体的对象类型,那么仍然应该存在某种现有逻辑,这种逻辑会为您提供此ContainsNestedList - T1关系,否则就是问题的前提没有坚持。

当您在代码中执行T2时,因为foreach (var v in l)lList<T1>也是v。此外,检查T1类型的v类型是否loopLoopClass表示T1object(非约束类型)或后代在loopLoopClass中,后者被转换为where T1 : loopLoopClass的约束。

鉴于您之后执行loopBody.OfTypeRecursive<T2>(),并且loopBody根据评论被称为List<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();
    }
}

编辑:更新以考虑以下前提

  

你有一个任意对象列表。其中一些对象属于ClassA类型。其他一些对象属于其他特定类,比如ClassB,它被定义为具有对象的内部列表,其中一些对象在类型中也可能是ClassAClassB

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;
    }
}

答案 2 :(得分:0)

请参阅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");
    }
  }
}

答案 3 :(得分:0)

问题在于你的定义

public List<object> loopLoopBody

就像错误消息告诉你的那样,对象没有方法

OfTypeRecursive

所以看起来您正在调用列表项上的方法,而不是列表中的方法。 您应该考虑使用T1和T2类型进行投射,而不是&#34; loopLoopClass&#34;和&#34;对象&#34;。也许这可以解决你的问题。