Язык программирования C#9 и платформа .NET5. Страница 210
Console.WriteLine(p.ToString()); } }}Модифицируйте вызывающий код для добавления и удаления элемента:
// Добавить новый элемент.people.Add(new Person("Fred", "Smith", 32));// Удалить элемент.people.RemoveAt(0);В результате запуска программы вы получите вывод следующего вида:
Action for this event: AddHere are the NEW items:Name: Fred Smith, Age: 32Action for this event: RemoveHere are the OLD items:Name: Peter Murphy, Age: 52На этом исследование различных пространств имен, связанных с коллекциями, завершено. В конце главы будет также объясняться, как и для чего строить собственные обобщенные методы и обобщенные типы.
Создание специальных обобщенных методов
Несмотря на то что большинство разработчиков обычно применяют обобщенные типы, имеющиеся в библиотеках базовых классов, существует также возможность построения собственных обобщенных методов и специальных обобщенных типов. Давайте посмотрим, как включать обобщения в свои проекты. Первым делом будет построен обобщенный метод обмена. Начните с создания нового проекта консольного приложения по имени
CustomGenericMethodsПостроение специальных обобщенных методов представляет собой более развитую версию традиционной перегрузки методов. В главе 2 вы узнали, что перегрузка — это действие по определению нескольких версий одного метода, которые отличаются друг от друга количеством или типами параметров.
Хотя перегрузка является полезным средством объектно-ориентированного языка, проблема заключается в том, что при этом довольно легко получить в итоге огромное количество методов, которые по существу делают одно и то же. Например, пусть необходимо создать методы, которые позволяют менять местами два фрагмента данных посредством простой процедуры. Вы можете начать с написания нового статического класса с методом, который способен оперировать целочисленными значениями:
using System;namespace CustomGenericMethods{ static class SwapFunctions { // Поменять местами два целочисленных значения. static void Swap(ref int a, ref int b) { int temp = a; a = b; b = temp; } }}Пока все идет хорошо. Но теперь предположим, что нужно менять местами также и два объекта
PersonSwap()// Поменять местами два объекта Person.static void Swap(ref Person a, ref Person b){ Person temp = a; a = b; b = temp;}Вне всяких сомнений вам должно быть ясно, чем все закончится. Если также понадобится менять местами два значения с плавающей точкой, два объекта растровых изображений, два объекта автомобилей, два объекта кнопок или что-нибудь еще, то придется писать дополнительные методы, что в итоге превратится в настоящий кошмар при сопровождении. Можно было бы построить один (необобщенный) метод, оперирующий с параметрами типа
objectНаличие группы перегруженных методов, отличающихся только входными аргументами — явный признак того, что обобщения могут облегчить ситуацию. Рассмотрим следующий обобщенный метод
Swap<T>()Т// Этот метод будет менять местами два элемента// типа, указанного в параметре <Т>.static void Swap<T>(ref T a, ref T b){ Console.WriteLine("You sent the Swap() method a {0}", typeof(T)); T temp = a; a = b; b = temp;}Обратите внимание, что обобщенный метод определен за счет указания параметра типа после имени метода, но перед списком параметров. Здесь заявлено, что метод
Swap<T>()<Т>typeof()Console.WriteLine("***** Fun with Custom Generic Methods *****\n");// Поменять местами два целочисленных значения.int a = 10, b = 90;Console.WriteLine("Before swap: {0}, {1}", a, b);SwapFunctions.Swap<int>(ref a, ref b);Console.WriteLine("After swap: {0}, {1}", a, b);Console.WriteLine();// Поменять местами два строковых значения.string s1 = "Hello", s2 = "There";Console.WriteLine("Before swap: {0} {1}!", s1, s2);