C# – generics方法与非generics方法
我有点困惑为什么/何时我想要使用generics方法,因为非generics方法可以访问其包含类的generics成员并且无论如何都要传递generics参数。
所以,使用一个可能会忽略这一点的jar头示例(但突出了我为什么要问这个问题),为什么我会这样做:
public class SomeGeneric { public T Swap(ref T a, ref T b) { T tmp = a; a = b; b = tmp; } }
过度
public class SomeGeneric { public T Swap(ref T a, ref T b) { T tmp = a; a = b; b = tmp; } }
这个?
或者,真的,为什么我要使用通用方法呢?
您通常在非generics的类型中使用generics方法。
例如,查看Enumerable
类 。 它定义了大多数LINQfunction的通用扩展方法,但它本身并不通用。
您还可能需要generics类型中的generics方法,但前提是generics方法使用不同的generics类型说明符。
这使您可以编写如下内容:
class Foo where T : IConvertible, IComparable { int CompareTo(U other) where U : IConvertible { // Convert to this T otherConverted = Convert.ChangeType(other, typeof(T)); return this.CompareTo(otherConverted); } }
(当然,这有点人为,但是对于Foo
进行编译和正常工作与double
等比较)
如果包含类不通用怎么办? 如果它有不同的generics类型参数怎么办?
第一个例子没有多大意义,因为没有使用类参数。 考虑另一个例子:
public class SomeGeneric { public K ConvertTo (T a) { return CodeThatConvertsTtoK(a); } }
及其用法: new SomeGeneric
如果类和方法都是通用的,那么类型参数(“通用参数”)当然必须具有不同的名称。 在你的第一个例子中,不能有两个不同的东西。
如果您的方法是非静态的(如图所示),如果您选择使包含类通用,则在实例化类时必须已指定类型。 像var obj = new SomeGeneric
。 所以它应该是逻辑上“属于”类所建模的对象的东西。
如果您的方法是静态的,并且您选择使该类具有通用性,那么您仍然必须以某种方式将类型参数与类一起指定。 如果从类外部调用该方法,它将像SomeGeneric
。
使方法通用的优点是,在许多情况下,您可以使用类型推断 ,它允许您省略角度括号类型参数。 您只能使用通用方法执行此操作 。 示例: nonGeneric.Swap(ref a, ref b);
其中Swap
方法是通用的。 编译器将查看a
和b
的编译时类型,并确定哪个T
适合,而不指定它。
结论:如果T
在逻辑上不属于类(如List
),请将其与方法一起使用。
方法级别类型参数的常见方案是扩展方法,因为它们必须在非generics静态类中声明。 但是非通用类型中的每个通用成员都需要它们。
public static class Extensions { public static void Foo(this A a, B b) { [...] } public static T Bar(this String input) { [...] } public static U FooBar(this V v, W w) { [...] } }