【问题标题】:C# specialization of generic extension methods泛型扩展方法的 C# 特化
【发布时间】:2012-12-13 08:33:15
【问题描述】:

我的MessageBus 有以下扩展方法:

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&lt;T&gt; 会 比T 更具体 还是不正确?

编辑

它变得更好奇,因为如果我调用扩展方法 然后明确:

MessageBus.SubscribeTo(source, bus);

然后它会工作并选择正确的方法。

【问题讨论】:

  • 你可以让它按预期工作:public static IDisposable Subscribe&lt;T&gt;( this IObservable&lt;T&gt; observable, MessageBus bus) where T : Maybe&lt;T&gt;
  • @2kay 通用约束不是候选解决过程的一部分,因此它不起作用

标签: c# generics extension-methods


【解决方案1】:

好吧,你可以通过指定类型参数来修复它:

source.Subscribe<string>(bus);

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

否则,编译器可能会调用以下任一方法:

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

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

例如,在 C# 4 规范(“更好的函数成员”)的第 7.5.3.2 节中,有一条关于:

  • 否则,如果 MP 比 MQ 具有更具体的参数类型,则 MP 优于 MQ子>。 [...很多关于更少/更具体的细节...]

...但是关于类型参数没有类似的观点。 (关于普通参数的第二个讨论类型参数,但那是在参数类型本身中。)

另一种选择是简单地为方法指定不同的名称。他们的行为有细微的不同吗?如果是这样,为什么不通过命名让它变得非常明显呢?您真的不希望某人仅仅因为他们对调用了哪个重载感到惊讶而做出错误的行为。

【讨论】:

  • 嗨乔恩。我已经通过直接调用扩展方法更新了这个问题,它给出了不同的结果。为什么扩展方法不能专门化,而直接调用却是。这是否符合您对标准的理解。
  • 在这种情况下,我将使用直接调用,因为它对我来说是编译时安全的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-12-21
  • 2015-07-19
  • 1970-01-01
相关资源
最近更新 更多