我可以为IEnumerable<;T>;比<;T>;
本文关键字:gt lt IEnumerable 我可以 | 更新日期: 2024-10-23 05:05:22
我有一个适用于任何类的扩展方法,但如果我在IEnumerable<T>
上工作,我想调用一个特殊的版本。
例如
public static class ExtensionMethods
{
public static dynamic Test<T>(this T source)
{
dynamic expandoObject = new System.Dynamic.ExpandoObject();
var dictionary = (IDictionary<string,object>)expandoObject;
dictionary["Test"] = source.ToString();
return dictionary;
}
public static IEnumerable<dynamic> Test<T>(this List<T> source)
{
var result = new List<dynamic>();
foreach(var r in source)
yield return r.Test();
}
public static IEnumerable<dynamic> Test<T>(this IEnumerable<T> source)
{
var result = new List<dynamic>();
foreach(var r in source)
yield return r.Test();
}
}
//使用
public class X
{
string guid = Guid.NewGuid().ToString();
}
void Main()
{
List<X> list = new List<X>() { new X() };
list.Test().Dump(); // Correct but only works because there is an explicit overload for List<T>
var array = list.ToArray();
((IEnumerable<X>) array).Test().Dump(); // Correct
array.Test().Dump(); // Calls the wrong extension method
}
有什么办法可以得到数组吗。Test()调用IEnumerable版本而不必显式强制转换它?
或者,如果我给扩展方法不同的名称,如果我不小心使用了错误的名称,是否有任何方法可以导致编译器错误?
我认为你试图朝着错误的方向解决它。List实现了IEnumerable接口,因此编译器在解决问题时可能会遇到问题。最好的方法将在List上调用。您可以做的是——您可以测试IEnumerable是否是扩展方法中的列表。
public static IEnumerable<dynamic> Test<T>(this IEnumerable<T> source)
{
if (source is List<T>) {
// here
}
var result = new List<dynamic>();
foreach(var r in source)
yield return r.Test();
}
您可以指定T
,而不依赖类型推理,这将提示编译器使用正确的扩展方法。代码如下:
var array = list.ToArray();
array.Test<X>().Dump();
实际情况是,编译器无法判断要使用哪个扩展,因为Array
是两个方法签名的有效参数:
public static dynamic Test<T>(this T source) { .. }
public static IEnumerable<dynamic> Test<T>(this IEnumerable<T> source) { .. }
在第一种情况下,编译器可以假定T
是Array
类型。因此,编译器必须选择一个(可能是第一个定义的?)。
添加此扩展方法以显式捕获所有数组类型:
public static IEnumerable<dynamic> Test<T>(this T[] source)
{
var result = new List<dynamic>();
foreach(var r in source)
yield return r.Test();
}