2012-03-25 21 views
43

我是C#的新手,並直接潛入修改我收到的項目的一些代碼。但是,我總是看到這樣的代碼:什麼是<T>在C#中表示

class SampleCollection<T> 

,我不能做什麼的

<T> 

手段,也不是什麼所謂的意義。

如果有人願意幫助我只是說出這個概念被稱爲什麼,我可以在網上搜索它。不過,我現在一無所知。

+0

Dupe of http://stackoverflow.com/questions/361336/what-are-generic-collections-in-c#361365和http://stackoverflow.com/questions/400314/what-does-t-mean -in-C。 – Abel 2012-03-25 18:33:49

+0

重複許多其他人,但也像其他人一樣脫離主題,因爲它需要[文檔](http://msdn.microsoft.com/en-us/library/512aeb7t.aspx)或教程。 – 2014-09-15 19:32:39

回答

71

這是一個Generic Type Parameter

通用類型參數允許您在編譯時爲方法指定任意類型T,而無需在方法或類聲明中指定具體類型。

例如:

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

逆轉數組中的元素。這裏的關鍵是數組元素可以是任何類型,並且該函數仍然可以工作。您在方法調用中指定類型;型式安全仍然有保證。

因此,要扭轉一個字符串數組:

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

會產生一個字符串數組中的{ "5", "4", "3", "2", "1" }

這具有相同的效果result,如果你曾呼籲普通(非通用)方法是這樣的:

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

編譯器看到的是array包含字符串,那麼它將返回STRI數組NGS。使用string代替T類型參數。


泛型類型參數也可用於創建泛型類。在您給出的SampleCollection<T>的示例中,T是任意類型的佔位符;這意味着SampleCollection可以表示對象的集合,這是您在創建集合時指定的對象的集合。

所以:

var collection = new SampleCollection<string>(); 

創建一個集合,可以容納字符串。上面所示的Reverse方法有些不同,可以用來反轉集合的成員。

+0

在運行時可以指定通用類型參數T的方式? – 2012-03-25 01:35:29

+0

@mikez:http://stackoverflow.com/questions/513952/c-sharp-specifying-generic-collection-type-param-at-runtime – 2012-03-25 01:41:37

+2

是的,雖然你可以在運行時使用反射實例化帶有類型參數的泛型類,說你使用泛型在運行時指定了一個類型,而你在正常使用時在編譯時指定了一個類型,這是令人困惑的。 – SoftMemes 2012-03-25 01:43:35

6

此功能被稱爲泛型。 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

11

它是一個通用類型參數,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>(); 

這種方式,您將有一個該添加元素列表只接受整數,因爲該類instancited與類型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