【问题标题】:Overload of generic method for IEnumerable<T>?IEnumerable<T> 的泛型方法重载?
【发布时间】:2016-10-09 11:25:11
【问题描述】:

我想要一个泛型方法的两个重载:

public ReturnType<T> DoStuff<T>(T thing) {...}

public ReturnType<T> DoStuff<T>(IEnumerable<T> things) {...}

当然,问题在于 IEnumerable&lt;T&gt; 本身就是一个匹配第一个签名的类型,所以当我尝试将一个集合传递给这个方法时,它会调用第一个重载。

显然,我可以用不同的方式命名这些方法以消除歧义。但鉴于这些方法本质上是做同样的事情,我想将它们保留为重载。

有没有办法在第一个签名中定义T,使其接受IEnumerable作为参数?

【问题讨论】:

  • 我不知道为重载类型“最佳”选择提供 exclusive 命令的可能性。您可能希望在第二种方法中添加一个虚拟参数并区分签名
  • 好吧,当您不传入该确切类型时,泛型类型 - 根据定义 - 比 IEnumerable&lt;T&gt; 更精确。您可以从调用者的角度更改它,方法是在此之前调用.AsEnumerable()

标签: c# generics


【解决方案1】:

这是一种 hack,但您可能会误认为只有在非扩展方法中找不到匹配项时才会考虑扩展方法。

class MyClass {
  public ReturnType<T> DoStuff<T>(IEnumerable<T> things) { ... }
  public ReturnType<T> DoStuffSingle<T>(T thing) { ... }
}

static class MyClassExtensions {
  public static ReturnType<T> DoStuff<T>(this MyClass myClass, T thing)
    => myClass.DoStuffSingle(thing);
}

在此之后,给定一个MyClass myClass;

  • myClass.DoStuff(123); 调用采用int 的扩展方法
  • myClass(new[] {123}); 调用采用IEnumerable&lt;int&gt; 的实例方法
  • myClass("123"); 调用采用IEnumerable&lt;char&gt; 的实例方法
  • myClass(t);,其中t 是一个不受约束的泛型参数类型T,调用采用T 的扩展方法,而不管T 实现了哪些接口。

在我看来,最后两个表明你可能不应该继续走这条路,但无论如何,没有什么能阻止你不同意并继续这样做。

【讨论】:

  • 偷偷摸摸。非常好!
  • 正如你所说,这表明设计存在问题,但很好的解决方法:)
  • 由于您提到的原因,我最终决定使用不同的方法名称。但这得到了答案,因为它是提供的最狡猾的黑客。 :-)
【解决方案2】:

我认为没有办法说你想要除了“除 X 之外的所有东西”,但你可以使用 generic constraints 来指定 T 应该是什么样的:

public ReturnType<T> DoStuff<T>(T thing) where T : IYourInterface {...}    
public ReturnType<T> DoStuff<T>(IEnumerable<T> things) where T : IYourInterface {...}

我认为没有办法(不添加更多代码)这样​​做是有道理的,因为泛型被编译为实际的类。如果您指定“除 X 之外的所有内容”,那么它应该编译成什么?它会有什么功能?..

要更好地理解为什么要使用T 而不仅仅是传递IYourInterface 参数,请参阅Difference between interface as type constraint and interface as parameter?。另外,this 可能会提供更多解释

【讨论】:

  • 在这种情况下,为什么还要麻烦T?只需将签名中的T 替换为IYourInterface。关键是这是一个泛型,这意味着它必须可用于任何类型,包括我没有想到的类型。
  • @ShaulBehr 如果您使用IEnumerable&lt;YourImplementation&gt; 调用它,您可能希望返回类型为ReturnType&lt;YourImplementation&gt; 而不是ReturnType&lt;IYourInterface&gt;。您可能是对的,这对您不起作用,但在其他情况下这是一种有效的方法。
  • @hvd 公平评论。但我的观点仍然是,这也需要适用于未实现 IYourInterface 的类。
猜你喜欢
  • 2011-06-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-03-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多