简体   繁体   English

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

[英]C# - generic methods vs. non-generic methods

I'm a bit confused about why/when I'd ever want to use a generic method since a non-generic method can access the generic members of its containing class and be passed generic arguments anyway. 我有点困惑为什么/何时我想要使用泛型方法,因为非泛型方法可以访问其包含类的泛型成员并且无论如何都要传递泛型参数。

So, using a canned example that likely misses the point (yet highlights why I'm asking this question), why would I do this: 所以,使用一个可能忽略这一点的罐头示例(但突出了我为什么要问这个问题),为什么我会这样做:

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

over 过度

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

this? 这个?

Or, really, why would I want to use a generic method at all ? 或者,真的,为什么我要在所有使用一个通用的方法是什么?

You'd typically use a generic method in a type that isn't generic. 您通常在非泛型的类型中使用泛型方法。

For example, look at the Enumerable class . 例如,查看Enumerable It defines the generic extension methods for most of the LINQ fucntionaltiy, but itself isn't generic. 它定义了大多数LINQ功能的通用扩展方法,但它本身并不通用。

You also might want a generic method within a generic type, but only if the generic method used a different generic type specifier. 您还可能需要泛型类型中的泛型方法,但前提是泛型方法使用不同的泛型类型说明符。

This lets you write something like the following: 这使您可以编写如下内容:

 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);
      }
 }

(Granted, this is a bit contrived, but does compile and work correctly for Foo<int> comparing to a double , etc) (当然,这有点做作,但是对于Foo<int>进行编译和正常工作,比较double等)

What if the containing class is not generic? 如果包含类不通用怎么办? What if it has different generic type parameters? 如果它有不同的泛型类型参数怎么办?

The first example does not make much sense, because class parameter is not used. 第一个例子没有多大意义,因为没有使用类参数。 Consider another example though: 考虑另一个例子:

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

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

If both the class and the method are generic, the type parameters ("generic parameters") must have different names, of course. 如果类和方法都是通用的,那么类型参数(“通用参数”)当然必须具有不同的名称。 There can't be two different things named T like in your first example. 不能有两个不同的东西叫T你的第一个例子一样。

If your method is non-static (as it seems), if you choose to make the containing class generic, the type will have to be specified already when you instantiate your class. 如果您的方法是非静态的(如图所示),如果您选择使包含类通用,则在实例化类时必须已指定类型。 Like var obj = new SomeGeneric<DateTime>(); var obj = new SomeGeneric<DateTime>(); . So it should be something that logically "belongs" to the object modelled by the class. 所以它应该是逻辑上“属于”类所建模的对象的东西。

If your method is static, and you choose to make the class generic, you will still have to specify the type parameter together with the class somehow. 如果您的方法是静态的,并且您选择使该类具有通用性,那么您仍然必须以某种方式将类型参数与类一起指定。 If the method is called from outside the class, it would go like SomeGeneric<DateTime>.Swap(ref a, ref b); 如果从类外部调用该方法,它将像SomeGeneric<DateTime>.Swap(ref a, ref b); .

The advantage with making the method generic, is that in many cases you can use type inference which allows you to omit the angle bracketed type parameter. 使方法通用的优点是,在许多情况下,您可以使用类型推断 ,它允许您省略角度括号类型参数。 You can only do this with generic methods . 您只能使用通用方法执行此操作 Example: nonGeneric.Swap(ref a, ref b); 示例: nonGeneric.Swap(ref a, ref b); where the Swap<T> method is generic. Swap<T>方法是通用的。 The compiler will look at the compile-time types of a and b and figure out which T fits in, without you specifying it. 编译器将查看ab的编译时类型,并确定哪个T适合,而不指定它。

Conclusion: If the T does not logically belong to the class (as in List<T> ), put it with the method. 结论:如果T在逻辑上不属于类(如List<T> ),请将其与方法一起使用。

A common scenario for method level type parameters are extension methods because they must be declared in a non-generic static class. 方法级别类型参数的常见方案是扩展方法,因为它们必须在非泛型静态类中声明。 But they are required for every generic member in a non-generic type. 但是非通用类型中的每个通用成员都需要它们。

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) { [...] }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM