|
Программирование >> Программирование с использованием ajax
В случае предоставления параметра обобщенному типу, как было в List<Card> выше, он может называться закрытым (closed) обобщенным типом, так же как и наследовани£ от List<T> может аналогичным образом называться наследованием от открытого (open) обобщенного типа. Обобщенные операции Переопределенные операции реализуются в С# точно так же, как и другие методы, и, следовательно, могут реализоваться и в обобщенных классах. Например, в Farm<T> можно определить следующую операцию неявного преобразования: public static implicit operator List<Animal>(Farm<T> farm) { List<Animal> result = new List<Animal> (); foreach (T animal in farm) result.Add(animal); return result; Это позволит при необходимости получать доступ к объектам Animal в Farm<T> напрямую как к List<Animal>. Подобное может оказаться удобным для сложения двух экземпляров Farm<T> с помощью, например, показанных ниже операций: public static Farm<T> operator +(Farm<T> farml, List<T> farm2) { Farm<T> result = new Farm<T>(); foreach (T animal in farml) { result.Animals.Add(animal); foreach (T animal in farm2) { if (!result.Animals.Contains(animal)) { result.Animals.Add(animal); return result; public static Farm<T> operator +(List<T> farml, Farm<T> farm2) { return farm2 + farml; Это позволит складывать вместе экземпляры Farm<Animal> и Farm<Cow> следующим образом: Farm<Animal> newFarm = farm + dairyFarm; В этом коде dairyFarm (экземпляр Farm<Cow>) неявно преобразуется в экземпляр List<Animal>, который пригоден для использования в перегруженной операции + в Farm<T>. Может показаться, что подобного легко добиться и путем использования следующего кода: public static Farm<T> operator +(Farm<T> farml, Farm<T> farm2) Farm<T> result = new Farm<T>(); foreach (T animal in farml) { result.Animals.Add(animal); foreach (T animal in farm2) if (!result.Animals.Contains(animal)) result.Animals.Add(animal); return result; Однако поскольку Farm<Cow> не может преобразовываться Farm<Animal>, операция суммирования будет заканчиваться ошибкой. Чтобы устранить эту проблему, можно воспользоваться следующей операцией преобразования: public static implicit operator Farm<Animal>(Farm<T> farm) { Farm<Animal> result = new Farm<Animal>(); foreach (T animal in farm) result.Animals.Add(animal); return result; При наличии такой операции экземпляры Farm<T>, вроде Farm<Cow> смогут преобразовываться в экземпляры Farm<Animal>, что устранит проблему. Применять можно любой из продемонстрированных методов, но последний все-таки более предпочтителен по причине простоты. Обобщенные структуры в предыдущих главах уже рассказывалось о том, что структуры выглядят, по сути, точно так же, как классы, и отличаются от них лишь незначительными деталями и тем, что представляют собой не ссылочные типы, а типы-значения. Благодаря этому, создавать обобщенные структуры можно аналогично обобщенным классам: public struct MyStruct<Tl, Т2> { public TI iteml; public T2 item2; Определение обобщенных интерфейсов в этой главе уже встречалось несколько обобщенных интерфейсов: в частности, это были интерфейсы из пространства имен Systems . Collections . Generic вроде IEnumerable<T>, который использовался в последнем примере. Для определения обобщенных интерфейсов применяются те же самые приемы, что и для определения обобщенных классов: interface MyFarminglnterfасе<Т> where Т : Animal { bool AttemptToBreed(Т animall, T animal2); T OldestlnHerd get; Здесь обобщенный параметр Т используется для указания типа в двух аргументах метода AttemptToBreed () и в свойстве OldestlnHerd. Правила наследования выглядят для обобщенных интерфейсов так же, как и для обобщенных классов. При выполнении наследования от базового обобщенного интерфейса, например, нужно не забывать о таком правиле, как сохранение ограничений параметров, представляющих обобщенный тип базового интерфейса. Определение обобщенных методов в последнем практическом занятии был использован метод GetCows (), в пояснениях к которому было сказано, что можно было бы создать и более универсальную версию данного метода, применив обобщенный метод. В этом разделе как раз и будет показано, как подобное возможно. Обобщенный метод - это такой метод, в котором возвращаемый тип и/или типы параметров определяются параметром или параметрами обобщенного типа: public Т GetDefault<T>() { return default (Т); В этом типичном примере, чтобы вернуть значение по умолчанию для типа Т используется рассматривавшееся ранее в главе ключевое слово default. Вызывается этот метод следующим образом: int myDefaultInt = GetDefault<T> (); Отвечающий за тип параметр Т предоставляется во время вызова метода. Этот тип Т идет отдельно от типов, используемых для предоставления классам параметров обобщенного типа. На самом деле обобщенные методы могут реализоваться и не обобщенными классами: public class Defaulter { public Т GetDefault<T>О { return default(T); Если класс является обобщенным, однако, тогда для типов обобщенного метода нужно обязательно использовать разные идентификаторы. Например, следующий код компилироваться не будет: public class Defaulter<T> public Т GetDefault<T>О { return default(T);
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |