我可以为IEnumerable <t>提供与<t>?</t> </t>不同的扩展方法

时间:2015-03-07 12:39:54

标签: c# extension-methods

我有一个适用于任何类的扩展方法,但如果我正在处理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
}

有没有什么方法可以让array.Test()调用IEnumerable版本而不必显式转换它?

或者,如果我给扩展方法赋予不同的名称,如果有任何方法,如果我意外地使用了错误的方法,我会遇到编译器错误?

3 个答案:

答案 0 :(得分:1)

我认为你正试图以错误的方向解决它。 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();          
}

答案 1 :(得分:0)

您可以指定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。因此,编译器必须选择一个(可能首先定义?)。

答案 2 :(得分:0)

添加此扩展方法以显式捕获所有数组类型:

public static IEnumerable<dynamic> Test<T>(this T[] source)
{
    var result = new List<dynamic>();
    foreach(var r in source)
        yield return r.Test();          
}
相关问题