Я просмотрел пример кода с использованием генераторов С#. Почему и когда я должен их использовать?
Все примеры были сложными. Мне нужен простой, ясный пример, который заставляет меня начать с С# generics.
Я просмотрел пример кода с использованием генераторов С#. Почему и когда я должен их использовать?
Все примеры были сложными. Мне нужен простой, ясный пример, который заставляет меня начать с С# generics.
Очень простой пример - это общий List<T>
класс. Он может содержать несколько объектов любого типа. Например, вы можете объявить список строк (new List<string>()
) или список Животные (new List<Animal>()
), поскольку он является общим.
Что делать, если вы не можете использовать дженерики? Вы можете использовать класс ArrayList
, но недостатком является то, что он содержит тип object
. Поэтому, когда вы будете перебирать список, вам нужно будет придать каждому элементу правильный тип (либо string
или Animal
), который больше кода и имеет ограничение производительности. Кроме того, поскольку объект ArrayList
содержит объекты, он не безопасен для типов. Вы все равно можете добавить Animal
в строку ArrayList
.
Например, с помощью ArrayList вы будете повторять так:
foreach((Animal)animal in myArrayList)
{
animal.Speak();
}
С общим списком вы можете просто использовать:
foreach(Animal animal in myAnimalList)
{
animal.Speak();
}
Кроме того, с общим List<string>
это невозможно!
List<string> stringList = new List<String>();
stringList.Add("Hello");
stringList.Add("Second String");
stringList.Add(new Animal()); // error! Animal cannot be cast to a string
Подводя итог другим ответам с некоторым упором:
1) generics позволяют вам писать "общий" код (т.е. он будет работать для нескольких типов). Если у вас есть "общее" поведение, которое вы хотите написать, что вам нужно вести для разных типов данных, вам нужно только один раз написать этот код. Пример списка - отличный пример, вам могут потребоваться списки клиентов, продуктов, заказов, поставщиков... все с использованием того же кода, созданного для каждого типа
// snippet
List<Customer> customers = new List<Customer>();
Customer thisCustomer = new Customer();
customers.Add(thisCustomer);
List<Order> orders = new List<Order>();
Order thatOrder = new Order();
orders.Add(thatOrder);
// etc.
2) удивительно, что дженерики все еще обеспечивают безопасность типов! Поэтому, если вы попробуете это, вы по праву получите сообщение об ошибке:
// continued for snippet above
Order anotherOrder = new Order();
customers.Add(anotherOrder); // FAIL!
И вы хотите, чтобы это было ошибкой, так что в дальнейшем код обработки вашего клиента не должен обрабатывать фиктивный заказ, отображаемый в списке клиентов.
Дублирование - это корень всего зла. Один случай дублирования кода возникает, когда вы должны выполнять такую же операцию для разных типов данных. Дженерики позволяют вам избежать этого, позволяя вам кодировать "общий" тип, а затем подставлять его конкретными типами.
Другим решением этой проблемы является использование переменных типа "System.Object", к которым может быть назначен объект любого типа. Этот метод включает операции бокса и распаковки между значениями и ссылочными типами, которые влияют на производительность. Кроме того, тип casting не дает коду быть чистым.
В MSIL и CLR поддерживаются дженерики, что делает его очень эффективным.
Вы должны прочитать эти статьи о дженериках -
http://msdn.microsoft.com/en-us/library/512aeb7t(VS.80).aspx
http://msdn.microsoft.com/en-us/library/ms379564(VS.80).aspx#csharp_generics_topic1
Вкратце, дженерики позволяют писать классы, которые работают с объектами любого типа, но без необходимости передавать данные в Object
. Для этого есть преимущества для производительности, но это также делает ваш код более читабельным, поддерживаемым и менее подверженным ошибкам.
Вы всегда должны использовать generics, а не классы классов .NET 1.1.