Ескертпе
Бұл бетке кіру үшін қатынас шегін айқындау қажет. Жүйеге кіруді немесе каталогтарды өзгертуді байқап көруге болады.
Бұл бетке кіру үшін қатынас шегін айқындау қажет. Каталогтарды өзгертуді байқап көруге болады.
Разработчики используют универсальные шаблоны все время в .NET, будь то неявно или явно. Когда вы используете LINQ в .NET, вы когда-либо заметили, что вы работаете с IEnumerable<T>? Или если вы когда-либо видели в Интернете пример универсального репозитория для взаимодействия с базами данных с помощью Entity Framework, вы видели, что большинство методов возвращают IQueryable<T>? Возможно, вы задались вопросом, что T находится в этих примерах и почему он там.
Впервые появившись в .NET Framework 2.0, универсальные шаблоны по сути являются "шаблоном кода", который позволяет разработчикам определять структуры данных, безопасные для типов , без фиксации фактического типа данных. Например, List<T> это универсальная коллекция, которую можно объявить и использовать с любым типом, например List<int>List<string>, или List<Person>.
Чтобы понять, почему универсальные шаблоны полезны, давайте рассмотрим конкретный класс до и после добавления универсальных шаблонов: ArrayList В .NET Framework 1.0 элементы ArrayList были типа Object. Любой элемент, добавленный в коллекцию, автоматически преобразуется в элемент Object. То же самое произойдет при чтении элементов из списка. Этот процесс называется упаковкой и распаковкой, что влияет на производительность. Кроме вопросов производительности, однако, нет способа определить тип данных в списке во время компиляции, что делает код уязвимым. Универсальные шаблоны решают эту проблему, определив тип данных каждого экземпляра списка. Например, можно добавлять только целые числа в List<int> и только людей в List<Person>.
Дженерики также доступны во время выполнения. Среда выполнения знает, какой тип структуры данных вы используете, и может хранить ее в памяти более эффективно.
В следующем примере показана небольшая программа, которая иллюстрирует эффективность знания типа структуры данных во время выполнения:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
namespace GenericsExample {
class Program {
static void Main(string[] args) {
//generic list
List<int> ListGeneric = new List<int> { 5, 9, 1, 4 };
//non-generic list
ArrayList ListNonGeneric = new ArrayList { 5, 9, 1, 4 };
// timer for generic list sort
Stopwatch s = Stopwatch.StartNew();
ListGeneric.Sort();
s.Stop();
Console.WriteLine($"Generic Sort: {ListGeneric} \n Time taken: {s.Elapsed.TotalMilliseconds}ms");
//timer for non-generic list sort
Stopwatch s2 = Stopwatch.StartNew();
ListNonGeneric.Sort();
s2.Stop();
Console.WriteLine($"Non-Generic Sort: {ListNonGeneric} \n Time taken: {s2.Elapsed.TotalMilliseconds}ms");
Console.ReadLine();
}
}
}
Эта программа создает выходные данные, аналогичные следующему:
Generic Sort: System.Collections.Generic.List`1[System.Int32]
Time taken: 0.0034ms
Non-Generic Sort: System.Collections.ArrayList
Time taken: 0.2592ms
Первое, что вы можете заметить здесь, заключается в том, что сортировка универсального списка значительно быстрее, чем сортировка не универсального списка. Вы также можете заметить, что тип универсального списка отличается ([System.Int32]), в то время как тип для не универсального списка обобщен. Так как среда выполнения знает, что универсальный List<int> имеет тип Int32, она может хранить элементы списка в базовом массиве целых чисел в памяти, а неуниверсальный ArrayList должен привести каждый элемент списка к объекту. Как показано в этом примере, дополнительные приведения данных занимают время и замедляют сортировку списка.
Дополнительное преимущество среды выполнения, знающей тип вашего обобщенного типа, — это улучшенный процесс отладки. При отладке универсального элемента в C#вы знаете, какой тип каждого элемента находится в структуре данных. Без универсальных шаблонов не было бы понятия о типе каждого элемента.