English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
Параметрические типы представляют собой общую форму, а не конкретную форму. В C# параметрические типы означают, что они не специфичны для определенного типа данных.
C# позволяет использовать параметры типа и не использовать конкретный тип данных для определения параметрических классов, интерфейсов, абстрактных классов, полей, методов, статических методов, свойств, событий, делегатов и операторов. Параметры типа - это占очники типов, которые определяются при создании экземпляра параметрического типа.
Параметрические типы объявляются с помощью параметров типа в скобках после типа, например TypeName<T>, где T - параметр типа.
Параметрические классы определяются параметрами типа в скобках после имени класса. Ниже определен параметрический класс.
class DataStore<T> { public T Data { get; set; } }
Верх, DataStore - это параметрический класс. T называется параметром типа и может использоваться в качестве типа поля, свойства, параметра метода, типа возвращаемого значения и типа делегата в классе DataStore. Например, Data - параметрическое свойство, потому что мы используем параметр типа T в качестве его типа, а не конкретный тип данных.
Вы также можете определить несколько параметров типов и разделить их запятыми.
class KeyValuePair<TKey, TValue> { public TKey Key { get; set; } public TValue Value { get; set; } }
Вы можете создать экземпляр параметрического класса, указав фактический тип в угловых скобках. Ниже создается экземпляр параметрического класса DataStore.
DataStore<string> store = new DataStore<string>();
Верх, мыstring при создании экземпляра указываем тип в угловых скобках. Таким образом, T будет заменен на любой тип T, используемый в классе, на этапе компиляции. Таким образом, тип свойства Data - string.
下图为泛型的工作方式。
您可以为Data属性分配一个字符串值。尝试分配除字符串以外的其他值将导致编译时错误。
DataStore<string> store = new DataStore<string>(); store.Data = "Hello World!"; // obj.Data = 123; //编译时错误
您可以为不同的对象指定不同的数据类型,如下所示。
DataStore<string> strStore = new DataStore<string>(); strStore.Data = "Hello World!"; //strStore.Data = 123; // 编译时错误 DataStore<int> intStore = new DataStore<int>(); intStore.Data = 100; //intStore.Data = "Hello World!"; // 编译时错误 KeyValuePair<int, string> kvp1 = new KeyValuePair<int, string>(); kvp1.Key = 100; kvp1.Value = "Hundred"; KeyValuePair<string, string> kvp2 = new KeyValuePair<string, string>(); kvp2.Key = "IT"; kvp2.Value = "Information Technology";
泛型类增加了可重用性。类型越多,可重用性就越高。然而,过多的泛化会使代码难以理解和维护。
泛型类可以是其他泛型或非泛型类或抽象类的基类。
泛型类可以派生自其他泛型或非泛型接口,类或抽象类。
泛型类可以包含泛型字段。但是,无法初始化。
class DataStore<T> { public T data; }
下面声明一个泛型数组。
class DataStore<T> { public T[] data = new T[10]; }
使用类型参数声明其返回类型或参数的方法称为泛型方法。
class DataStore<T> { private T[] _data = new T[10]; public void AddOrUpdate(int index, T item) { if(index >= 0 && index < 10) _data[index] = item; } public T GetData(int index) { if(index >= 0 && index < 10) return _data[index]; else return default(T); } }
Методы AddorUpdate() и GetData() являются генерическими методами. Реальный тип данных параметра item будет указан при инстанцировании класса DataStore<T>, как показано ниже.
DataStore<string> cities = new DataStore<string>(); cities.AddOrUpdate(0, "Mumbai"); cities.AddOrUpdate(1, "Chicago"); cities.AddOrUpdate(2, "London"); DataStore<int> empIds = new DataStore<int>(); empIds.AddOrUpdate(0, 50); empIds.AddOrUpdate(1, 65); empIds.AddOrUpdate(2, 89);
Типы параметров генериков могут использоваться вместе с несколькими параметрами, имеющими или не имеющими негенерических параметров и типов возвращаемых значений. Вот примеры эффективных перегрузок генерических методов.
public void AddOrUpdate(int index, T data) { } public void AddOrUpdate(T data1, T data2) { } public void AddOrUpdate<U>(T data1, U data2) { } public void AddOrUpdate(T data) { }
Используя имя метода в скобках尖括ых для указания параметра типа, негенерический класс может содержать генерические методы, как показано ниже.
class Printer { public void Print<T>(T data) { Console.WriteLine(data); } } Printer printer = new Printer(); printer.Print<int>(100); printer.Print(200); // Инференция значения по указанному значению printer.Print<string>("Hello"); printer.Print("World!"); // Инференция значения по указанному значению
Генерика повышает повторное использование кода. Вам не нужно писать код для обработки различных типов данных.
Генерика безопасна по типу. Если попытка использовать данные типа, отличного от указанного в определении, то会出现 ошибку в время компиляции.
Генерика имеет преимущества в производительности, так как устраняет возможность装箱а и распаковки.