【问题标题】:What does <T> denote in C# [duplicate]<T> 在 C# 中表示什么 [重复]
【发布时间】:2012-03-25 01:23:59
【问题描述】:

我是 C# 新手,直接潜入修改我收到的项目的一些代码。但是,我一直看到这样的代码:

class SampleCollection<T>

我无法理解

<T> 

意思也不是它叫什么。

如果有人愿意帮助我说出这个概念的名称,我可以在线搜索。但是,我现在一无所知。

【问题讨论】:

标签: c# .net generics


【解决方案1】:

这是一个Generic Type Parameter

泛型类型参数允许您在编译时为方法指定任意类型 T,而无需在方法或类声明中指定具体类型。

例如:

public T[] Reverse<T>(T[] array)
{
    var result = new T[array.Length];
    int j=0;
    for(int i=array.Length - 1; i>= 0; i--)
    {
        result[j] = array[i];
        j++;
    }
    return result;
}

反转数组中的元素。这里的关键点是数组元素可以是任何类型,并且函数仍然可以工作。您在方法调用中指定类型;类型安全仍然得到保证。

所以,要反转一个字符串数组:

string[] array = new string[] { "1", "2", "3", "4", "5" };
var result = reverse(array);

将在result{ "5", "4", "3", "2", "1" } 中生成一个字符串数组

这与调用普通(非泛型)方法的效果相同,如下所示:

public string[] Reverse(string[] array)
{
    var result = new string[array.Length];
    int j=0;
    for(int i=array.Length - 1; i >= 0; i--)
    {
        result[j] = array[i];
        j++;
    }
    return result;
}

编译器看到array 包含字符串,所以它返回一个字符串数组。类型 string 替换了 T 类型参数。


泛型类型参数也可用于创建泛型类。在您给出的SampleCollection&lt;T&gt; 示例中,T 是任意类型的占位符;这意味着SampleCollection 可以表示对象的集合,您在创建集合时指定对象的类型。

所以:

var collection = new SampleCollection<string>();

创建一个可以保存字符串的集合。上面说明的Reverse 方法以稍微不同的形式,可用于反转集合的成员。

【讨论】:

  • 在运行时可以通过什么方式指定泛型类型参数T?
  • 是的,尽管您可以在运行时使用反射来实例化具有类型参数的泛型类,但如果说您使用泛型在运行时指定一个类型,而在正常使用情况下在编译时指定一个类型,这会让人感到困惑.
  • 但问题似乎是关于泛型类型,而不是泛型方法。
  • @ulkas: From here:"对于泛型类的偏好是使用泛型接口,比如IComparable而不是IComparable,以避免对上的装箱和拆箱操作值类型。”
【解决方案2】:

它是一个泛型类型参数,see Generics documentation

T 不是保留关键字。 T或任何给定名称,表示类型参数。检查以下方法(仅作为简单示例)。

T GetDefault<T>()
{
    return default(T);
}

注意返回类型是T。使用此方法,您可以通过以下方式调用该方法来获取任何类型的默认值:

GetDefault<int>(); // 0
GetDefault<string>(); // null
GetDefault<DateTime>(); // 01/01/0001 00:00:00
GetDefault<TimeSpan>(); // 00:00:00

.NET 在集合中使用泛型,...示例:

List<int> integerList = new List<int>();

这样你会得到一个只接受整数的列表,因为类被实例化为T,在本例中为int,添加元素的方法写成:

public class List<T> : ...
{
    public void Add(T item);
}

更多关于泛型的信息。

你可以限制T类型的范围。

以下示例仅允许您使用类类型调用方法:

void Foo<T>(T item) where T: class
{
}

以下示例仅允许您调用具有 Circle 类型或从其继承的方法。

void Foo<T>(T item) where T: Circle
{
}

还有new() 说如果它有一个无参数的构造函数,你可以创建一个T 的实例。在以下示例中,T 将被视为Circle,您将获得智能感知...

void Foo<T>(T item) where T: Circle, new()
{
    T newCircle = new T();
}

由于T是一个类型参数,你可以从中得到对象Type。使用Type,您可以使用反射...

void Foo<T>(T item) where T: class
{
    Type type = typeof(T);
}

作为一个更复杂的例子,检查ToDictionary 或任何其他Linq 方法的签名。

public static Dictionary<TKey, TSource> ToDictionary<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector);

没有T,但有TKeyTSource。建议您始终使用前缀T 命名类型参数,如上所示。

如果你愿意,你可以命名TSomethingFoo

【讨论】:

    【解决方案3】:

    此功能称为泛型。 http://msdn.microsoft.com/en-us/library/512aeb7t(v=vs.100).aspx

    这方面的一个例子是创建一个特定类型的项目的集合。

    class MyArray<T>
    {
        T[] array = new T[10];
    
        public T GetItem(int index)
        {
            return array[index];
        }
    }
    

    在您的代码中,您可以执行以下操作:

    MyArray<int> = new MyArray<int>();
    

    在这种情况下,T[] array 会像 int[] array 一样工作,public T GetItem 会像 public int GetItem 一样工作。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-05-27
      • 1970-01-01
      相关资源
      最近更新 更多