简体   繁体   English

我可以为IEnumerable使用不同的Extension方法吗? <T> 而不是 <T> ?

[英]Can I have a different Extension method for IEnumerable<T> than for <T>?

I have an extension method that works on any class, but I want to call a special version if I am working on IEnumerable<T> . 我有一个适用于任何类的扩展方法,但如果我正在处理IEnumerable<T> ,我想调用一个特殊版本。

For Example 例如

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

// Usage //用法

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
}

Is there any way I can get array.Test() to call the IEnumerable version without having to explicitly cast it? 有没有办法让array.Test()调用IEnumerable版本而不必显式转换它?

Alternatively, if I give the extension method different names, if there any way I can get a compiler error if I accidently use the wrong one? 或者,如果我给扩展方法赋予不同的名称,如果有任何方法,如果我意外地使用了错误的名称,我会得到编译器错误?

I think you are trying to solve it in a wrong direction. 我想你正试图以错误的方向解决它。 The List implements IEnumerable interface and as such the compiler can have problem with solving the best method will be invoked on List. List实现IEnumerable接口,因此编译器可能有问题解决将在List上调用的最佳方法。 What you could do -- you could test if the IEnumerable is a list inside the extension method. 你可以做什么 - 你可以测试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();          
}

You can specify T and not rely on type inference, this will hint compiler to use correct extension method. 您可以指定T而不依赖于类型推断,这将提示编译器使用正确的扩展方法。 Code would look like this: 代码看起来像这样:

var array = list.ToArray();
array.Test<X>().Dump();

What happens is, that compiler cannot tell which extension to use, since Array is valid argument for both method signatures: 会发生什么,编译器无法分辨使用哪个扩展,因为Array是两个方法签名的有效参数:

public static dynamic Test<T>(this T source) { .. }

public static IEnumerable<dynamic> Test<T>(this IEnumerable<T> source) { .. }

In first case compiler can assume T is of type Array . 在第一种情况下,编译器可以假设TArray类型。 Because of it, compiler has to picks one (might be first defined?). 因此,编译器必须选择一个(可能首先定义?)。

Add this extension method to explicitly catch all array types: 添加此扩展方法以显式捕获所有数组类型:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM