2012-12-13 103 views
11

我有我的MessageBus以下扩展方法:C#专业化

public static class MessageBusMixins 
{ 
    public static IDisposable Subscribe<T>(
     this IObservable<T> observable, 
     MessageBus bus) 
    where T:class 
    { 
     ... 
    } 

    public static IDisposable Subscribe<T>( 
     this IObservable<Maybe<T>> observable, 
     MessageBus bus) 
    { 
     ... 
    } 
} 

它编译罚款。然而,当我尝试使用它:

IObservable<Maybe<string>> source = ...; 
MessageBus bus = ...; 

source.Subscribe(bus); 

我得到的错误,无论是两个候选方法 是最特殊的。不过,我认为Maybe<T>会 是更多具体比T还是那不正确?

编辑

它变得不寻常了,因为如果我调用扩展方法 明确,那么:

MessageBus.SubscribeTo(source, bus); 

然后,它的工作原理,并挑选正确的方法。

+0

你可以把它按预期工作:'公共静态IDisposable的订阅( 此的IObservable 观察到, MessageBus总线),其中T:也许' – 2kay

+0

,T不能或许 bradgonesurfing

+3

@ 2kay通用约束不是的一部分候选人解决​​过程中,这样不会起作用 – SWeko

回答

9

好了,你可以通过指定类型参数修正:

source.Subscribe<string>(bus); 

...因为这是现在只有第二种方法是适用的。

否则,编译器可以调用之一:

source.Subscribe<string>(bus); 
source.Subscribe<Maybe<string>>(bus); 

如果你想到的第一比第二更具体的,你必须要找到其中是这么说的:)这是C#规范的规则不是一个不合理的期望,但我不认为认为正常的“更具体”转换适用于类型参数以及常规参数。

因此,例如,在部分C#4规格( “更好的函数成员”)的7.5.3.2有一个规则有关:

  • 否则,如果M P有更具体的参数类型比M Q,则M P优于M Q。 [...许多关于更少/更具体的细节...]

...但有关于类型参数没有类似的观点。 (关于正常参数的第二个参数讨论类型参数,但这属于参数类型本身。)

另一种替代方法是简单地给方法不同的名称。他们有不同的行为吗?如果是这样,为什么不通过命名做出真正的明显?你真的不希望有人因为他们对所谓的超载感到惊讶而得到错误的行为。

+1

嗨,乔恩。我通过直接调用扩展方法更新了问题,它给出了不同的结果。为什么扩展方法无法专门化,而直接调用却是不可能的。这是否符合你对标准的理解。 – bradgonesurfing

+0

在这种情况下,我会直接调用,因为编译时对我来说是安全的。 – bradgonesurfing