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;
}
}
注意:ContainsNestedList
的 Name
属性 仅用于视觉识别目的。
如果您无法控制具体的对象类型,仍然应该有某种现有逻辑可以为您提供这种 T1
- T2
关系,否则问题的前提撑不住了。
当您在代码中执行 foreach (var v in l)
时,因为 l
是一个 List<T1>
,v
也是一个 T1
。此外,检查 v
的类型是 loopLoopClass
的类型意味着 T1
是 object
(非约束类型)或 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();
}
}
编辑:更新以说明以下前提
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;
}
}
我有一个包含不同种类对象的列表,有时这些对象有自己的列表。因此,为了获得列表 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;
}
}
注意:ContainsNestedList
的 Name
属性 仅用于视觉识别目的。
如果您无法控制具体的对象类型,仍然应该有某种现有逻辑可以为您提供这种 T1
- T2
关系,否则问题的前提撑不住了。
当您在代码中执行 foreach (var v in l)
时,因为 l
是一个 List<T1>
,v
也是一个 T1
。此外,检查 v
的类型是 loopLoopClass
的类型意味着 T1
是 object
(非约束类型)或 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();
}
}
编辑:更新以说明以下前提
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, sayClassB
, which is defined as having an inner list of objects, some of which might also beClassA
orClassB
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;
}
}