我希望有两个泛型方法的重载:
^.*POST .*(wp-login|xmlrpc)\.php.*(403|499)*
麻烦当然是public ReturnType<T> DoStuff<T>(T thing) {...}
public ReturnType<T> DoStuff<T>(IEnumerable<T> things) {...}
本身就是一个与第一个签名匹配的类型,所以当我尝试将一个集合传递给这个方法时,它会调用第一个重载。
显然,我可以用不同的方式命名方法以消除歧义。但是看到方法基本上做同样的事情,我想把它们作为重载。
是否有某种方法可以在第一个签名中定义IEnumerable<T>
,以便不接受T
作为参数?
答案 0 :(得分:4)
这是一个黑客攻击,但你可以滥用扩展方法仅在非扩展方法中找不到匹配时考虑的事实。
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<int>
myClass("123");
调用IEnumerable<char>
myClass(t);
,其中t
是无约束的通用参数类型T
,无论T
实现哪个接口,都会调用T
的扩展方法。 在我看来,最后两个表明你可能不应该继续沿着这条路走下去,但是没有什么可以阻止你不同意并且不管怎么说。
答案 1 :(得分:0)
我认为没有办法说除了“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可能会提供更多解释