是接口扩展方法视为低优先级低于具体的呢? [英] Are extension methods for interfaces treated as lower priority than less specific ones?

查看:108
本文介绍了是接口扩展方法视为低优先级低于具体的呢?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下的扩展类:

public static class MatcherExtensions
{
    public static ExecMatcher<T1, T2> Match<T1, T2>(this Tuple<T1, T2> item)
    {
        return new ExecMatcher<T1, T2>(item.Item1, item.Item2);
    }

    public static ExecMatcher<T1, T2> Match<T1, T2>(this ITupleMatchable<T1, T2> item)
    {
        var tuple = item.PropertiesToMatch;
        return new ExecMatcher<T1, T2>(tuple.Item1, tuple.Item2);
    }

    public static ExecMatcher<T> Match<T>(this T item) { return new ExecMatcher<T>(item); }
}

如果我创建了一个元组,并调用匹配( ),它正确使用第一个扩展方法:

If I create a tuple and invoke Match(), it correctly uses the first extension method:

var tuple = Tuple.Create(1, "a");
tuple.Match().With(1, "a")...   // compiles just fine.

如果我创建了一个int和调用匹配(),它正确使用最后一个扩展方法:

If I create a int and invoke Match(), it correctly uses the last extension method:

var one = 1;
one.Match().With(1)... // compiles just fine.



但是,如果我创建 SomeClass的,它实现 ITupleMatchable< INT,串> ,并尝试和匹配就可以了,编译器仍然选择了第三个扩展方法,而不是第二个,尽管后者是一个更具体的匹配:

However if I create SomeClass, which implements ITupleMatchable<int, string> and try and match on it, the compiler still chooses the third extension method, rather than the second one, despite the latter being a more specific match:

var obj = new SomeClass(1, "a");
obj.Match().With(1, "a")... // won't compile.

根据的埃里克利珀的回答类似的问题,我已经解决这个通过将第三个扩展方法变成自己的一流的子目录中,从而创造它和调用代码之间比一个较长的命名空间,让更多的距离的工作具体到 ITupleMatchable<版本; T1,T2> 。这感觉就像一个黑客对我来说虽然。是否有解决这个的更简洁的方式?

Based on Eric Lippert's answer to a similar question, I have worked around this by putting the third extension method into its own class within a subdirectory, thus creating a longer namespace and so more "distance" between it and the calling code than for the version specific to ITupleMatchable<T1, T2>. This feels like a hack to me though. Is there a neater way of resolving this?

推荐答案

如果你简单地把新SomeClass的(1, A) ITupleMatchable< INT,串> ,这将正常工作:

If you simply cast new SomeClass(1, "a") to ITupleMatchable<int, string>, it will work fine:

var obj = (ITupleMatchable<int, string>)new SomeClass(1, "a");
obj.Match().With(1, "a");



记住,你的 OBJ 变量,否则有编译时间 SomeClass的的类型。编译器可以更容易实际的类由具有看的接口实现匹配到第三扩展方法(它是兼容的任何的类型),比它可以SomeClass的,然后将其匹配例如:第二个扩展方法。

Remember that your obj variable otherwise has a compile-time type of SomeClass. The compiler can "more easily" match the actual class to the third extension method (which is compatible with any type), than it can by having to look at the interface implementations of SomeClass and then matching it to e.g. the second extension method.

但是,如果你提供的这个参数作为真实的接口类型,然后第二次延长方法是更合适的,因为它完全方法是寻找,而不是更广泛的任何类型的类型。即这是一个更具体的声明,所以是更好。

But if you provide the this parameter as the actual interface type, then the second extension method is a better fit, because it's exactly the type the method is looking for, rather than being the broader "any type". I.e. it's a more specific declaration, and so is "better".

请注意,一旦扩展方法的候选集被找到(通过与命名空间等规则) ,是用正常的重载决议确定的实际方法。即已经确定在 MatcherExtensions 类是一个合格的扩展方法至少有一个方法,编译器则与正常重载决策规则去那些中进行选择。你可以找到在C#5.0规范这些规则,节 7.5.3

Note that once the candidate set of extension methods is found (via rules relating to the namespace, etc.), the actual method is determined using normal overload resolution. I.e. having determined that at least one method in your MatcherExtensions class is an eligible extension method, the compiler then goes with the normal overload resolution rules to pick among those. You can find those rules in the C# 5.0 specification, section 7.5.3.

虽然简单:申请前的重载决策规则(事实上,为了确定哪些方法甚至资格),注意,编译器已经决定了泛型类型参数。所以,它计算的重载解析,它正在以匹配(SomeClass的项目)匹配(ITupleMatchable< INT,串>的项目)。我们希望,一旦你认为,你就会明白为什么,如果变量的类型为 SomeClass的,编译器通过第二优先挑选你的第三次延期,以及一个副反之亦然,如果类型为 ITupleMatchable< INT,串方式>

Briefly though: before applying the overload resolution rules (indeed, in order to determine which methods are even eligible), note that the compiler has already decided the generic type parameters. So, as it evaluates the overload resolution, it is looking at Match(SomeClass item) and Match(ITupleMatchable<int, string> item). Hopefully once you consider that, you'll see why, if the variable has the type SomeClass, the compiler picks your third extension preferentially over the second, and vice a versa if the type is ITupleMatchable<int, string>.

这篇关于是接口扩展方法视为低优先级低于具体的呢?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆