АвтоАвтоматизацияАрхитектураАстрономияАудитБиологияБухгалтерияВоенное делоГенетикаГеографияГеологияГосударствоДомДругоеЖурналистика и СМИИзобретательствоИностранные языкиИнформатикаИскусствоИсторияКомпьютерыКулинарияКультураЛексикологияЛитератураЛогикаМаркетингМатематикаМашиностроениеМедицинаМенеджментМеталлы и СваркаМеханикаМузыкаНаселениеОбразованиеОхрана безопасности жизниОхрана ТрудаПедагогикаПолитикаПравоПриборостроениеПрограммированиеПроизводствоПромышленностьПсихологияРадиоРегилияСвязьСоциологияСпортСтандартизацияСтроительствоТехнологииТорговляТуризмФизикаФизиологияФилософияФинансыХимияХозяйствоЦеннообразованиеЧерчениеЭкологияЭконометрикаЭкономикаЭлектроникаЮриспунденкция

Создание пользовательских обобщенных коллекций

Читайте также:
  1. В нашем доме пожар? Создание театра медиа в период информационных войн
  2. Внешняя политика СССР в 1945-1885гг: изменения на международной арене, создание мировой социалистической системы, этапы холодной войны.
  3. Вопрос 7. Структура денежной массы. Создание денег банковской системой. Депозитный и денежный мультипликатор.
  4. Глава 1 Создание специальных служб Финляндии 1914-1919гг.
  5. Задание 1. Создание запроса на выборку из двух таблиц с помощью мастера.
  6. Задание 1. Создание связи «один – ко – многим».
  7. Задание 1. Создание слайдов с анимацией.
  8. Задание 2. Создание вычисляемых полей в запросах.
  9. Задание 2. Создание нового поля с использованием подстановки значений из другой таблицы.
  10. Задание 2. Создание таблицы Документы МНТ
  11. Задание 2. Создание таблицы с помощью конструктора
  12. Задание 3. Создание поля типа гиперссылка

Итак, пространство имен System.Collections.Generic предлагает множество типов, позволяющих создавать эффективные контейнеры, удовлетворяющие требованиям типовой безопасности. С учетом множества доступных вариантов очень велика вероятность того, что в.NET 2.0 у вас вообще не возникнет необходимости в построении пользовательских типов коллекции. Тем не менее, чтобы показать, как строится обобщенный контейнер, нашей следующей задачей будет создание обобщенного класса коллекции, который мы назовем CarCollection<T>.

Подобно созданному выше необобщенному типу CarCollection, наш новый вариант будет использовать уже существующий тип коллекции для хранения своих элементов (в данном случае это List<>). Будет реализована и поддержка цикла foreach путем реализации обобщенного интерфейса IEnumerable<>. Обратите внимание на то, что IEnumerable<> расширяет необобщенный интерфейс IEnumerable, поэтому компилятор ожидает, что вы реализуете две версии метода GetEnumerator(). Вот как может выглядеть соответствующая модификация.

public class CarCollection<T>: IEnumerable<T>{ private List<T> arCars = new List<T>(); public T GetCar(int pos) { return arCars[pos]; } public void AddCar(T c) { arCars.Add(c); } public void ClearCars() { arCars.Clear(); } public int Count { get { return arCars.Count; } } // IEnumerable<T> расширяет IEnumerable, поэтому // нужно реализовать обе версии GetEnumerator(). IEnumerator<T> IEnumerable<T>.GetEnumerator() { return arCars.GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return arCars.GetEnumerator(); } }

Этот обновленный тип CarCollection<T> можно использовать так.

static void Main(string[] args){ Console.WriteLine("* Пользовательская обобщенная коллекция *\n"); // Создание коллекции объектов Car. CarCollection<Car> myCars = new CarCollection<Car>(); myCars.AddCar(new Car("Rusty", 20)); myCars.AddCar(new Car("Zippy", 90)); foreach (Car c in myCars) { Console.WriteLine("PetName: {0}, Speed: {1}", c.PetName, c.Speed); } Console.ReadLine(); }

При создании обобщенных методов для вас может оказаться сюрпризом появление ошибок компилятора, когда с параметрами типа используются операции C# (+, -, *, == и т.д.). Например, я уверен, вы сочли бы полезными классы Add(), Subtract(), Multiply() и Divide(), способные работать с обобщенными типами.

// Ошибка компиляции! // Нельзя применять операции к параметрам типа! public class BasicMath<T>{ public T Add(T arg1, T arg2) { return arg1 + arg2; } public T Subtract(T arg1, T arg2) { return arg1 - arg2; } public T Multiply(T arg1, T arg2) { return arg1 * arg2; } public T Divide(T arg1, T arg2) { return arg1 / arg2; } }

Как ни печально, этот класс BasicMath<T> не компилируется. Это может показаться большим ограничением, но не следует забывать, что обобщения являются обобщениями. Конечно, тип System.Int32 может прекрасно работать с бинарными операциями C#. Однако, если, например, <T> будет пользовательским классом или типом структуры, компилятор не сможет сделать никаких предположений о характере перегруженных операций +, -, * и /.

Перед рассмотрением обобщенных интерфейсов следует указать на то, что обобщенные классы могут быть базовыми для других классов и могут таким образом определять любое число виртуальных и абстрактных методов. Однако производные типы должны подчиняться определенным правилам, вытекающим из природы обобщенной абстракции. Во-первых, если обобщенный класс расширяется необобщенным, то производный класс должен конкретизироватьпараметр типа.

// Предположим, что создан пользовательский // обобщенный класс списка. public class MyList<T> { private List<T> listOfData = new List<T>();} // Конкретные типы должны указать параметр типа, // если они получаются из обобщенного // базового класса. public class MyStringList: MyList<string> {}

Кроме того, если обобщенный базовый класс определяет обобщенные виртуальные или абстрактные методы, производный тип должен переопределить эти обобщенные методы, используя конкретизированный параметр типа.

// Обобщенный класс с виртуальным методом. public class MyList<T>{ private List<T> listOfData = new List<T>(); public virtual void PrintList(T data) { } } public class MyStringList: MyList<string> { // В производных методах нужно заменить параметр типа, // используемый в родительском классе. public override void PrintList(string data) { } }

Если производный тип тоже является обобщенным, дочерний класс может (опционально) использовать заменитель типа в своем определении. Однако знайте, что любые ограничения, размещенные в базовом классе, должны “учитываться” и производным типом. Например:

// Обратите внимание, теперь здесь имеется ограничение, // требующее конструктор по умолчанию. public class MyList<T> where T: new(){ private List<T> listOfData = new List<T>(); public virtual void PrintList(T data) { } } // Производный тип должен учитывать ограничения базового. public class MyReadOnlyList<T>: MyList<T> where T: new(){ public override void PrintList(T data) { } }

Если вы только не планируете построить свою собственную библиотеку обобщений, вероятность того, что вам придется строить иерархии обобщенных классов, оказывается практически нулевой. Тем не менее, вы теперь знаете, что язык C# обеспечивает поддержку наследования обобщений.


1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 |

Поиск по сайту:



Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Студалл.Орг (0.003 сек.)