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

C#-泛型方法与非泛型方法,c#,generics,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<T>(ref T a, ref T b)
    {
        T tmp = a;
        a = b;
        b = tmp;
    }
}
公共类
{
公共T交换(参考T a、参考T b)
{
T tmp=a;
a=b;
b=tmp;
}
}
结束

公共类
{
公共T交换(参考T a、参考T b)
{
T tmp=a;
a=b;
b=tmp;
}
}
这个


或者,真的,我为什么要使用泛型方法呢?

如果包含的类不是泛型的呢?如果它有不同的泛型类型参数怎么办?

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

例如,请看。它为大多数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,其中T:IConvertible,IComparable
{
int CompareTo(U其他),其中U:i可转换
{
//转换成这个
T otherConverted=Convert.ChangeType(其他,typeof(T));
返回此.CompareTo(其他已转换);
}
}

(当然,这有点做作,但与双精度等相比,它确实可以为
Foo
正确编译和工作)

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

public class SomeGeneric<T>
{
    public K ConvertTo<T>(T a)
    {
         return CodeThatConvertsTtoK(a);
    }
}
公共类
{
公共K转换器(TA)
{
返回代码转换sttok(a);
}
}
及其用法:
newsomegeneric().ConvertToInt(“十”)

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

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) { [...] }
}
公共静态类扩展
{
公共静态void Foo(这是A,B){[…]}
公共静态T条(此字符串输入){[…]}
公共静态U FooBar(这个V,W){[…]}
}

如果类和方法都是泛型的,那么类型参数(“泛型参数”)当然必须有不同的名称。在第一个示例中,不能有两个不同的名称
t

如果您的方法是非静态的(看起来如此),如果您选择使包含类成为泛型的,那么在实例化类时必须已经指定类型。比如
var obj=newsomegeneric()。因此,它应该在逻辑上“属于”由类建模的对象

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

使该方法通用的优点是,在许多情况下,您可以使用类型推断,它允许您省略尖括号中的类型参数。您只能使用泛型方法执行此操作。示例:
nonGeneric.Swap(参考a、参考b)其中
交换
方法是通用的。编译器将查看
a
b
的编译时类型,并找出哪个
T
适合,而无需指定它


结论:如果
T
在逻辑上不属于该类(如
List
),请将其与方法放在一起。

在大多数情况下,方法或类都是泛型的。很少两者兼而有之。在您的第一个示例中,这实际上是一个问题,因为T在类和方法定义之间是不明确的;它们应该有不同的名称,但在语义上,您不希望使用不同的类型。需要两个泛型参数,一个在类级别,一个在方法级别,这是非常罕见的。这应该是
public K ConvertTo(ta)
(编译器会按原样抱怨)
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) { [...] }
}