C# - 泛型方法与非泛型方法

时间:2012-12-19 19:08:51

标签: c# generics

我有点困惑为什么/何时我想要使用泛型方法,因为非泛型方法可以访问其包含类的泛型成员并且无论如何都要传递泛型参数。

所以,使用一个可能会忽略这一点的罐头示例(但突出了我为什么要问这个问题),为什么我会这样做:

public class SomeGeneric<T>
{
    public T Swap<T>(ref T a, ref T b)
    {
        T tmp = a;
        a = b;
        b = tmp;
    }
}

public class SomeGeneric<T>
{
    public T Swap(ref T a, ref T b)
    {
        T tmp = a;
        a = b;
        b = tmp;
    }
}

此?

或者,真的,为什么我要在所有中使用通用方法

5 个答案:

答案 0 :(得分:9)

您通常在非通用的类型中使用泛型方法。

例如,查看Enumerable class。它定义了大多数LINQ功能的通用扩展方法,但它本身并不通用。

您也可能需要泛型类型中的泛型方法,但前提是泛型方法使用不同的泛型类型说明符。

这可以让您编写如下内容:

 class Foo<T> where T : IConvertible, IComparable<T>
 {
      int CompareTo<U>(U other) where U : IConvertible
      {
           // Convert to this
           T otherConverted = Convert.ChangeType(other, typeof(T));
           return this.CompareTo(otherConverted);
      }
 }

(当然,这有点做作,但与Foo<int>相比,double编译并正常工作,等等)

答案 1 :(得分:4)

如果包含的类不是通用的,该怎么办?如果它有不同的泛型类型参数怎么办?

答案 2 :(得分:2)

第一个例子没有多大意义,因为没有使用类参数。考虑另一个例子:

public class SomeGeneric<T>
{
    public K ConvertTo<T>(T a)
    {
         return CodeThatConvertsTtoK(a);
    }
}

及其用法: new SomeGeneric<int>().ConvertToInt("ten");

答案 3 :(得分:1)

如果类和方法都是通用的,那么类型参数(“通用参数”)必须具有不同的名称。在第一个例子中,不能有两个不同的名为T的东西。

如果您的方法是非静态的(如图所示),如果您选择使包含类通用,则在实例化类时必须已指定类型。像var obj = new SomeGeneric<DateTime>();一样。所以它应该是逻辑上“属于”由类建模的对象的东西。

如果您的方法是静态的,并且您选择使该类具有通用性,那么您仍然必须以某种方式将类型参数与类一起指定。如果从类外部调用该方法,它将类似于SomeGeneric<DateTime>.Swap(ref a, ref b);

使方法通用的优点是,在许多情况下,您可以使用类型推断,它允许您省略角度括号类型参数。您只能使用通用方法执行此操作。示例:nonGeneric.Swap(ref a, ref b);其中Swap<T>方法是通用的。编译器将查看ab的编译时类型,并确定哪个T适合,而不指定它。

结论:如果T在逻辑上不属于该类(如List<T>中所述),请将其与方法一起使用。

答案 4 :(得分:0)

方法级别类型参数的常见方案是扩展方法,因为它们必须在非泛型静态类中声明。但是非通用类型中的每个通用成员都需要它们。

public static class Extensions
{
    public static void Foo<A, B>(this A a, B b) { [...] }

    public static T Bar<T>(this String input) { [...] }

    public static U FooBar<V, W>(this V v, W w) { [...] }
}