C#中的通用扩展方法:在这种边缘情况下会发生什么?

Tom*_*han 6 c# generics extension-methods

在我最近的一个问题中,我了解到如果有多个扩展方法具有与给定类型匹配的约束,则将选择最具体的扩展方法.这让我思考 - 编译器如何确定哪一个"更具体"?结果会是什么?

假设我有以下课程:

public MyClass : IComparable, IDisposable
{
    // Implementation of members
}

public static class MyExtensions
{
    public static void DoSomething<T>(this T item)
        where T : IComparable
    { /* whatever */ }

    public static void DoSomething<T>(this T item)
        where T : IDisposable
    { /* whatever else */ }
}
Run Code Online (Sandbox Code Playgroud)

如果我现在使用扩展方法

var instance = new MyClass();
instance.DoSomething();
Run Code Online (Sandbox Code Playgroud)

将使用哪种方法?或者编译器会抛出错误?

注意:我不是说这是好设计,甚至我说我需要这样做.但是"更具体"这个词足以让我思考这一点,现在我必须知道!:P

更新: 我想我是不是真的作为感兴趣的东西在上面的例子中会发生,如为什么.因为我做过类似的事情,所以我想到了

public static class CollectionExtensions
{
    public static void DoSomething<T>(this T items) where T : IList { ... }
    public static void DoSomething<T>(this T items) where T : IEnumerable { ... }
}
Run Code Online (Sandbox Code Playgroud)

编译器知道选择第一种方法的地方new List<Something>().DoSomething(),因为它与传递的类型"更接近".我当时感兴趣的是" 在这种情况下更接近的意思是什么?如果约束来自两个不同的继承链,编译器将如何反应?为什么?"

Jon*_*eet 6

在这种情况下,扩展类不会编译 - 您不能仅基于泛型约束重载方法.

如果你把两个扩展方法放到不同的类中,那么调用代码就不会编译 - 这将是一个模糊的调用,因为这两种方法都不会比另一种方法"更好"...在这两种情况下泛型类型的参数都是推断为MyClass,所以只希望有两次转换,从MyClassMyClass,这两者都不是优于其他.

一旦您发现没有适用的实例方法,这基本上只是一个特殊的重载情况.我最近刚写了一篇关于重载文章,你可能觉得它很有用 - 它没有提到这个具体的情况,但是如果你想详细看一下,它就指向规范的相关部分.