Главная страница
Навигация по странице:

  • Результат выполнения программы (из листинга 7.8)

  • Результат выполнения программы (из листинга 7.10)

  • Ограничения на параметры типа

  • Табл. 7.1. Ограничения на обобщенные параметрыВыражение Значение

  • Васильев А.Н. Основы программирования на C#. Васильев А. Н. Программирование


    Скачать 5.54 Mb.
    НазваниеВасильев А. Н. Программирование
    АнкорВасильев А.Н. Основы программирования на C
    Дата20.09.2022
    Размер5.54 Mb.
    Формат файлаpdf
    Имя файлаVasilev_Programmirovanie-na-C-dlya-nachinayushchih-Osobennosti-y.pdf
    ТипДокументы
    #686596
    страница28 из 40
    1   ...   24   25   26   27   28   29   30   31   ...   40
    Обобщенные структуры
    Здравствуйте! Мы пацаки с планеты Земля.
    из к/ф «Кин-дза-дза»
    Структуры также могут быть обобщенными. Принцип описания и использования обобщенных структур, в общем-то, такой же, как ив случае с обобщенными классами. Просто нужно помнить, что мы имеем дело со структурами, со всеми вытекающими отсюда последствиями. Пример использования обобщенных структур представлен в листинге 7.7.
    Обобщенные типы
    351
    
    Листинг 7.7. Знакомство с обобщенными структурами System;
    //
    Ɉɛɨɛɳɟɧɧɚɹ ɫɬɪɭɤɬɭɪɚ:
    struct MyStruct{
    //
    ɉɨɥɹ ɨɛɨɛɳɟɧɧɵɯ ɬɢɩɨɜ:
    public X first;
    public Y second;
    //
    Ʉɨɧɫɬɪɭɤɬɨɪ:
    public MyStruct(X a,Y b){
    first=a;
    second=b;
    }
    //
    Ɇɟɬɨɞ ɞɥɹ ɨɬɨɛɪɚɠɟɧɢɹ ɡɧɚɱɟɧɢɣ ɩɨɥɟɣ:
    public void show(){
    Console.WriteLine(
    Ǝɉɟɪɜɨɟ ɩɨɥɟ: {0}Ǝ,first);
    Console.WriteLine(
    Ǝȼɬɨɪɨɟ ɩɨɥɟ: {0}Ǝ,second);
    }
    }
    //
    Ƚɥɚɜɧɵɣ ɤɥɚɫɫ:
    class GenStructDemo{
    //
    Ƚɥɚɜɧɵɣ ɦɟɬɨɞ:
    static void Main(){
    //
    ɋɨɡɞɚɧɢɟ ɷɤɡɟɦɩɥɹɪɚ ɫɬɪɭɤɬɭɪɵ:
    MyStruct A;
    //
    ɉɪɢɫɜɚɢɜɚɧɢɟ ɡɧɚɱɟɧɢɣ ɩɨɥɹɦ ɷɤɡɟɦɩɥɹɪɚ ɫɬɪɭɤɬɭɪɵ:
    A.first=
    ƎMyStructƎ;
    A.second=100;
    //
    ȼɵɡɨɜ ɦɟɬɨɞɚ ɢɡ ɷɤɡɟɦɩɥɹɪɚ ɫɬɪɭɤɬɭɪɵ:
    A.show();
    //
    ɋɨɡɞɚɧɢɟ ɷɤɡɟɦɩɥɹɪɚ ɫɬɪɭɤɬɭɪɵ:
    MyStruct B=new MyStruct(
    ƍBƍ,200);
    //
    ȼɵɡɨɜ ɦɟɬɨɞɚ ɢɡ ɷɤɡɟɦɩɥɹɪɚ ɫɬɪɭɤɬɭɪɵ:
    Глава 7
    352
    B.show();
    Результат выполнения программы следующий:
    
    Результат выполнения программы (из листинга 7.7)
    ɉɟɪɜɨɟ ɩɨɥɟ: MyStruct
    ȼɬɨɪɨɟ ɩɨɥɟ: 100
    ɉɟɪɜɨɟ ɩɨɥɟ: B
    ȼɬɨɪɨɟ ɩɨɥɟ: Программа представляет собой упрощенный вариант предыдущего примера, нона этот раз мы вместо обобщенного класса использовали обобщенную структуру. Структура называется MyStruct, и у нее два обобщенных параметра (обозначены как X и Y). В структуре описаны два поля обобщенного типа, конструктор с двумя аргументами и метод show()
    для отображения значений полей. В главном методе программы создаются экземпляры структуры, полям экземпляров в случае необходимости присваиваются значения. Для поверки значений полей экземпляров структуры вызывается метод Обобщенные интерфейсы

    А, вот видишь у вас такой же оголтелый расизм, как и здесь, на Плюке! Только власть захватили не чатлане, а пацаки.
    из к/ф «Кин-дза-дза»
    Интерфейс также может быть обобщенным. Класс, который создается путем реализации обобщенного интерфейса, может быть либо обобщенным, либо обычным. Пример в листинге 7.8 иллюстрирует эту ситуацию.
    
    Листинг 7.8. Знакомство с обобщенными интерфейсами System;
    //
    Ɉɛɨɛɳɟɧɧɵɣ ɢɧɬɟɪɮɟɣɫ:
    Обобщенные типы MyInterface{
    void set(X a,Y b);
    void show();
    }
    //
    Ɉɛɨɛɳɟɧɧɵɣ ɤɥɚɫɫ ɪɟɚɥɢɡɭɟɬ ɨɛɨɛɳɟɧɧɵɣ ɢɧɬɟɪɮɟɣɫ:
    class Alpha:MyInterface{
    private X first;
    private Y second;
    public void set(X a,Y b){
    first=a;
    second=b;
    }
    public void show(){
    Console.WriteLine(
    Ǝɉɨɥɹ {0} ɢ {1}Ǝ,first,second);
    }
    }
    //
    Ɉɛɨɛɳɟɧɧɵɣ ɤɥɚɫɫ ɪɟɚɥɢɡɭɟɬ ɨɛɨɛɳɟɧɧɵɣ ɢɧɬɟɪɮɟɣɫ:
    class Bravo:MyInterface{
    private int first;
    private Y second;
    public void set(int a,Y b){
    first=a;
    second=b;
    }
    public void show(){
    Console.WriteLine(
    Ǝɉɨɥɹ {0} ɢ {1}Ǝ,first,second);
    }
    }
    //
    Ɉɛɵɱɧɵɣ ɤɥɚɫɫ ɪɟɚɥɢɡɭɟɬ ɨɛɨɛɳɟɧɧɵɣ ɢɧɬɟɪɮɟɣɫ:
    class Charlie:MyInterface{
    private int first;
    private char second;
    Глава 7
    354
    public void set(int a,char b){
    first=a;
    second=b;
    }
    public void show(){
    Console.WriteLine(
    Ǝɉɨɥɹ {0} ɢ {1}Ǝ,first,second);
    }
    }
    //
    Ƚɥɚɜɧɵɣ ɤɥɚɫɫ:
    class GenInterfaceDemo{
    //
    Ƚɥɚɜɧɵɣ ɦɟɬɨɞ:
    static void Main(){
    Console.WriteLine(
    Ǝɉɟɪɜɵɣ ɨɛɴɟɤɬƎ);
    //
    ɋɨɡɞɚɧɢɟ ɨɛɴɟɤɬɚ ɧɚ ɨɫɧɨɜɟ ɨɛɨɛɳɟɧɧɨɝɨ ɤɥɚɫɫɚ:
    Alpha A=new Alpha();
    //
    ɂɫɩɨɥɶɡɨɜɚɧɢɟ ɢɧɬɟɪɮɟɣɫɧɨɣ ɩɟɪɟɦɟɧɧɨɣ:
    MyInterface Ra=A;
    //
    ȼɵɡɨɜ ɦɟɬɨɞɨɜ:
    A.set(
    ƎAlphaƎ,100.0);
    Ra.show();
    Ra.set(
    ƎalphaƎ,150.0);
    A.show();
    Console.WriteLine(
    Ǝȼɬɨɪɨɣ ɨɛɴɟɤɬƎ);
    //
    ɋɨɡɞɚɧɢɟ ɨɛɴɟɤɬɚ ɧɚ ɨɫɧɨɜɟ ɨɛɨɛɳɟɧɧɨɝɨ ɤɥɚɫɫɚ:
    Bravo B=new Bravo();
    //
    ɂɫɩɨɥɶɡɨɜɚɧɢɟ ɢɧɬɟɪɮɟɣɫɧɨɣ ɩɟɪɟɦɟɧɧɨɣ:
    MyInterface Rb=B;
    //
    ȼɵɡɨɜ ɦɟɬɨɞɨɜ:
    B.set(200,
    ƎBravoƎ);
    Rb.show();
    Rb.set(250,
    ƎbravoƎ);
    B.show();
    Обобщенные типы Console.WriteLine(
    ƎɌɪɟɬɢɣ ɨɛɴɟɤɬƎ);
    //
    ɋɨɡɞɚɧɢɟ ɨɛɴɟɤɬɚ ɧɚ ɨɫɧɨɜɟ ɨɛɵɱɧɨɝɨ ɤɥɚɫɫɚ:
    Charlie C=new Charlie();
    //
    ɂɫɩɨɥɶɡɨɜɚɧɢɟ ɢɧɬɟɪɮɟɣɫɧɨɣ ɩɟɪɟɦɟɧɧɨɣ:
    MyInterface Rc=C;
    //
    ȼɵɡɨɜ ɦɟɬɨɞɨɜ:
    C.set(300,'C');
    Rc.show();
    Rc.set(350,
    ƍDƍ);
    C.show();
    Результат выполнения программы представлен ниже:
    
    Результат выполнения программы (из листинга 7.8)
    ɉɟɪɜɵɣ ɨɛɴɟɤɬ
    ɉɨɥɹ Alpha ɢ 100
    ɉɨɥɹ alpha ɢ 150
    ȼɬɨɪɨɣ ɨɛɴɟɤɬ
    ɉɨɥɹ 200 ɢ Bravo
    ɉɨɥɹ 250 ɢ bravo
    Ɍɪɟɬɢɣ ɨɛɴɟɤɬ
    ɉɨɥɹ 300 ɢ C
    ɉɨɥɹ 350 ɢ Мы описали обобщенный интерфейс MyInterface с двумя обобщенными параметрами X и Y. В интерфейсе объявлены два метода. Метод set()
    не возвращает результат, и у него два аргумента обобщенных типов. Метод show() не возвращает результат, и у него нет аргументов. Любой класс, реализующий интерфейс MyInterface, должен содержать описание этих методов.
    Также мы описываем три класса, реализующих интерфейс MyInterface. Класс Alpha является обобщенным с двумя обобщенными параметрами
    Глава 7
    356
    X
    и Y. Класс реализует интерфейс с теми же параметрами (соответствующая инструкция в описании класса имеет вид MyInterface). В классе есть два закрытых поля first и second обобщенных типов, метод set(), предназначенный для присваивания значений полям, а также метод show(), отображающий значение полей в консольном окне.
    Класс Bravo также является обобщенными у него только один обобщенный параметр (обозначен как Y). В классе реализуется интерфейс
    MyInterface
    , но для первого обобщенного параметра для этого интерфейса указано значение int. Соответственно, инструкция, определяющая реализуемый интерфейс, имеет вид MyInterface. Класс
    Bravo описан подобно классу Alpha, но только одно поле относится к типу int, а второе поле относится к обобщенному типу. Соответствующим образом описан и метод Класс Charlie является обычным (не обобщенным. Он реализует версию обобщенного интерфейса MyInterface, нос явно указанными значениями и char для обобщенных параметров.
    В главном методе программы создаются объекты классов Alpha, Bravo и Charlie. Кроме этого, объявляются интерфейсные переменные, которым в качестве значения присваиваются ссылки на соответствующие объекты. При объявлении интерфейсных переменных указываются имя интерфейса ив угловых скобках значения обобщенных параметров. Значения обобщенных параметров, указанные при объявлении интерфейсных переменных, должны соответствовать значениям обобщенных параметров, использованных при создании объекта НАЗ А МЕТКУ Напомним, что интерфейсная переменная может ссылаться на объект любого класса, который реализует данный интерфейс. Через интерфейсную переменную можно получить доступ только к тем методам объекта, которые объявлены в интерфейсе
    Обобщенные типы
    357
    Обобщенные классы и наследование А фамилию, позвольте узнать Фамилию Я согласен наследственную при- нять.
    из к/ф Собачье сердце»
    Рассмотренный в предыдущем разделе механизм реализации обобщенных интерфейсов применим и к наследованию классов. Идея очень простая один класс может наследовать другой класс, даже если последний является обобщенным. При этом производный класс может быть как обобщенным, таки обычным. В программе в листинге 7.9 приведен пример, похожий например из предыдущего разделано вместо реализации интерфейса задействовано наследование обобщенного абстрактного класса.
    
    Листинг 7.9. Наследование обобщенных классов System;
    //
    Ɉɛɨɛɳɟɧɧɵɣ ɚɛɫɬɪɚɤɬɧɵɣ ɤɥɚɫɫ:
    abstract class MyClass{
    //
    ɉɨɥɹ ɨɛɨɛɳɟɧɧɨɝɨ ɬɢɩɚ:
    protected X first;
    protected Y second;
    //
    Ⱥɛɫɬɪɚɤɬɧɵɟ ɦɟɬɨɞɵ:
    abstract public void set(X a,Y b);
    abstract public void show();
    }
    //
    Ɉɛɨɛɳɟɧɧɵɣ ɤɥɚɫɫ ɧɚɫɥɟɞɭɟɬ ɨɛɨɛɳɟɧɧɵɣ ɚɛɫɬɪɚɤɬɧɵɣ ɤɥɚɫɫ:
    class Alpha:MyClass{
    public override void set(X a,Y b){
    first=a;
    second=b;
    }
    public override void show(){
    Глава 7
    358
    Console.WriteLine(
    Ǝɉɨɥɹ {0} ɢ {1}Ǝ,first,second);
    }
    }
    //
    Ɉɛɨɛɳɟɧɧɵɣ ɤɥɚɫɫ ɧɚɫɥɟɞɭɟɬ ɨɛɨɛɳɟɧɧɵɣ ɚɛɫɬɪɚɤɬɧɵɣ ɤɥɚɫɫ:
    class Bravo:MyClass{
    public override void set(int a,Y b){
    first=a;
    second=b;
    }
    public override void show(){
    Console.WriteLine(
    Ǝɉɨɥɹ {0} ɢ {1}Ǝ,first,second);
    }
    }
    //
    Ɉɛɵɱɧɵɣ ɤɥɚɫɫ ɧɚɫɥɟɞɭɟɬ ɨɛɨɛɳɟɧɧɵɣ ɚɛɫɬɪɚɤɬɧɵɣ ɤɥɚɫɫ:
    class Charlie:MyClass{
    public override void set(int a,char b){
    first=a;
    second=b;
    }
    public override void show(){
    Console.WriteLine(
    Ǝɉɨɥɹ {0} ɢ {1}Ǝ,first,second);
    }
    }
    //
    Ƚɥɚɜɧɵɣ ɤɥɚɫɫ:
    class GenInterfaceDemo{
    //
    Ƚɥɚɜɧɵɣ ɦɟɬɨɞ:
    static void Main(){
    Console.WriteLine(
    Ǝɉɟɪɜɵɣ ɨɛɴɟɤɬƎ);
    //
    ɋɨɡɞɚɧɢɟ ɨɛɴɟɤɬɚ ɧɚ ɨɫɧɨɜɟ ɨɛɨɛɳɟɧɧɨɝɨ ɤɥɚɫɫɚ:
    Alpha A=new Alpha();
    //
    ɂɫɩɨɥɶɡɨɜɚɧɢɟ ɨɛɴɟɤɬɧɨɣ ɩɟɪɟɦɟɧɧɨɣ ɛɚɡɨɜɨɝɨ
    Обобщенные типы //
    ɚɛɫɬɪɚɤɬɧɨɝɨ ɤɥɚɫɫɚ:
    MyClass Ra=A;
    //
    ȼɵɡɨɜ ɦɟɬɨɞɨɜ:
    A.set(
    ƎAlphaƎ,100.0);
    Ra.show();
    Ra.set(
    ƎalphaƎ,150.0);
    A.show();
    Console.WriteLine(
    Ǝȼɬɨɪɨɣ ɨɛɴɟɤɬƎ);
    //
    ɋɨɡɞɚɧɢɟ ɨɛɴɟɤɬɚ ɧɚ ɨɫɧɨɜɟ ɨɛɨɛɳɟɧɧɨɝɨ ɤɥɚɫɫɚ:
    Bravo B=new Bravo();
    //
    ɂɫɩɨɥɶɡɨɜɚɧɢɟ ɨɛɴɟɤɬɧɨɣ ɩɟɪɟɦɟɧɧɨɣ ɛɚɡɨɜɨɝɨ
    //
    ɚɛɫɬɪɚɤɬɧɨɝɨ ɤɥɚɫɫɚ:
    MyClass Rb=B;
    //
    ȼɵɡɨɜ ɦɟɬɨɞɨɜ:
    B.set(200,
    ƎBravoƎ);
    Rb.show();
    Rb.set(250,
    ƎbravoƎ);
    B.show();
    Console.WriteLine(
    ƎɌɪɟɬɢɣ ɨɛɴɟɤɬƎ);
    //
    ɋɨɡɞɚɧɢɟ ɨɛɴɟɤɬɚ ɧɚ ɨɫɧɨɜɟ ɨɛɵɱɧɨɝɨ ɤɥɚɫɫɚ:
    Charlie C=new Charlie();
    //
    ɂɫɩɨɥɶɡɨɜɚɧɢɟ ɨɛɴɟɤɬɧɨɣ ɩɟɪɟɦɟɧɧɨɣ ɛɚɡɨɜɨɝɨ
    //
    ɚɛɫɬɪɚɤɬɧɨɝɨ ɤɥɚɫɫɚ:
    MyClass Rc=C;
    //
    ȼɵɡɨɜ ɦɟɬɨɞɨɜ:
    C.set(300,
    ƍCƍ);
    Rc.show();
    Rc.set(350,
    ƍDƍ);
    C.show();
    }
    }
    Глава Результат выполнения программы такой же, как ив предыдущем случае см. Листинг Результат выполнения программы (из листинга 7.9)
    ɉɟɪɜɵɣ ɨɛɴɟɤɬ
    ɉɨɥɹ Alpha ɢ 100
    ɉɨɥɹ alpha ɢ 150
    ȼɬɨɪɨɣ ɨɛɴɟɤɬ
    ɉɨɥɹ 200 ɢ Bravo
    ɉɨɥɹ 250 ɢ bravo
    Ɍɪɟɬɢɣ ɨɛɴɟɤɬ
    ɉɨɥɹ 300 ɢ C
    ɉɨɥɹ 350 ɢ В этой программе мы описали абстрактный обобщенный класс MyClass с двумя обобщенными параметрами (обозначены как X и Y). В классе объявлены два поля first и second обобщенных типов, а также абстрактные методы set() и show(). Классы Alpha, Bravo и Charlie наследуют (но по-разному) абстрактный базовый класс
    MyClass
    . В производных класса переопределяются методы set() и show(). В главном методе программы создаются объекты классов
    Alpha
    , Bravo и Charlie, а также проверяется работа методов set() и Обобщенные делегаты Ну и зараза же ты, родной Он хуже. Он просто кю!
    из к/ф «Кин-дза-дза»
    Обобщенным может быть делегат. При объявлении обобщенного делегата обобщенные параметры указываются в угловых скобках после имени делегата. При создании экземпляра делегата значения обобщенных параметров указываются в угловых скобках после названия делегата. Как все это выглядит на практике, показано в листинге 7.10.
    Обобщенные типы
    361
    
    Листинг 7.10. Обобщенный делегат System;
    //
    Ɉɛɨɛɳɟɧɧɵɣ ɞɟɥɟɝɚɬ:
    delegate X GenMeth(Y arg);
    //
    Ʉɥɚɫɫ:
    class MyClass{
    //
    ɐɟɥɨɱɢɫɥɟɧɧɨɟ ɩɨɥɟ:
    public int code;
    //
    Ɇɟɬɨɞ ɫ ɫɢɦɜɨɥɶɧɵɦ ɚɪɝɭɦɟɧɬɨɦ ɜɨɡɜɪɚɳɚɟɬ ɫɢɦɜɨɥɶɧɵɣ
    //
    ɪɟɡɭɥɶɬɚɬ:
    public char getChar(char start){
    return (char)(start+code);
    }
    }
    //
    Ƚɥɚɜɧɵɣ ɤɥɚɫɫ:
    class GenDelegateDemo{
    //
    ɋɬɚɬɢɱɟɫɤɢɣ ɦɟɬɨɞ ɫ ɰɟɥɨɱɢɫɥɟɧɧɵɦ ɚɪɝɭɦɟɧɬɨɦ
    //
    ɜɨɡɜɪɚɳɚɟɬ ɬɟɤɫɬɨɜɵɣ ɪɟɡɭɥɶɬɚɬ:
    static string getStr(int num){
    return
    Ǝɑɢɫɥɨ Ǝ+num;
    }
    //
    ɋɬɚɬɢɱɟɫɤɢɣ ɦɟɬɨɞ ɫ ɬɟɤɫɬɨɜɵɦ ɚɪɝɭɦɟɧɬɨɦ ɜɨɡɜɪɚɳɚɟɬ
    //
    ɰɟɥɨɱɢɫɥɟɧɧɵɣ ɪɟɡɭɥɶɬɚɬ:
    static int getInt(string txt){
    return Int32.Parse(txt);
    }
    //
    Ƚɥɚɜɧɵɣ ɦɟɬɨɞ:
    static void Main(){
    //
    Ɉɛɴɟɤɬ ɤɥɚɫɫɚ:
    MyClass obj=new MyClass();
    obj.code=5;
    Глава 7
    362
    //
    ɗɤɡɟɦɩɥɹɪɵ ɨɛɨɛɳɟɧɧɨɝɨ ɞɟɥɟɝɚɬɚ:
    GenMeth A=getStr;
    GenMeth B=new GenMeth(getInt);
    GenMeth C=obj.getChar;
    //
    ȼɵɡɨɜ ɷɤɡɟɦɩɥɹɪɨɜ ɞɟɥɟɝɚɬɚ:
    Console.WriteLine(A(123));
    Console.WriteLine(B(
    Ǝ100Ǝ)+200);
    Console.WriteLine(C(
    ƍAƍ));
    При выполнении программы получаем такой результат:
    
    Результат выполнения программы (из листинга 7.10)
    ɑɢɫɥɨ 123 В программе мы объявляем обобщенный делегат GenMeth с двумя обобщенными параметрами X и Y. В соответствии с описанием делегата, экземпляр делегата может ссылаться на метод, который имеет один аргумент типа Y и возвращает результат типа X. Фактически это означает, что при создании экземпляра делегата в качестве метода, на который экземпляр будет ссылаться, можно выбрать любой метод с одним аргументом, возвращающий результат.
    В программе описан класс MyClass с целочисленным полем code. В классе есть метод getChar(). У метода символьный аргумент, и метод возвращает символьный результат. Результат метода вычисляется так к коду символа, переданного аргументом методу, прибавляется значение поля code, и полученное значение является кодом символа-ре- зультата.
    В главном классе описано несколько статических методов. Методу getStr()
    в качестве аргумента передается целочисленное значение, а результатом метод возвращает текстовую строку, получающуюся объединением текста
    Ǝɑɢɫɥɨ Ǝ и значения аргумента метода
    Обобщенные типы
    363
    Статический метод getInt(), как предполагается, аргументом получает текстовое представление для целого числа, а результатом возвращает собственно число из текста (фактически метод дублирует работу статического метода Parse() из структуры В главном методе программы создается объект obj класса MyClass, полю code этого объекта присваивается значение 5, после чего ссылка на метод getChar() объекта используется в команде, которой создается экземпляр для обобщенного делегата GenMeth. После имени делегата указаны значения для обобщенных параметров. Команды
    GenMeth
    A=getStr и GenMeth B=new
    GenMeth(getInt)
    также дают представление о том, как создаются экземпляры обобщенного делегата. Созданные экземпляры делегата вызываются в главном методе.
    Ограничения на параметры типа
    Уйди отсюда Как советовать, так все — чатла- не, а как работать, так...
    из к/ф «Кин-дза-дза»
    В некоторых случаях при описании обобщенных методов, классов, структур, интерфейсов или делегатов необходимо наложить ограничения назначения для обобщенных параметров. Например, ограничение может быть таким значением обобщенного параметра должно быть только имя класса. Или наоборот, имя класса не может быть значением обобщенного параметра. Или значением обобщенного параметра должно быть имя класса, являющегося производным от какого-то определенного класса, итак далее. Все это можно реализовать, причем достаточно легко.
    Если обобщенный параметр не может принимать произвольное значение, а должен соответствовать определенным критериям, тов описании соответствующего обобщенного класса, метода, структуры, интерфейса или делегата указывается специальная инструкция, которая начинается с ключевого слова where. После этого ключевого слова следует название параметра (для которого определяется ограничение) и через двоеточие некоторое выражение. Это выражение, собственно, и определяет
    Глава ограничение, накладываемое на обобщенный параметр. Наиболее характерные случаи представлены в табл. 7.1 (далее через T обозначен обобщенный параметр).
    Табл. 7.1. Ограничения на обобщенные параметры
    Выражение
    Значение
    where T: Значением обобщенного параметра T может быть имя класса where T: Значением обобщенного типа T может быть только не- ссылочный тип (базовый тип или структура T: Значением обобщенного параметра T может быть тип, для которого предусмотрен конструктор без аргументов. Если на обобщенный параметр накладывается несколько ограничений, то данное ограничение должно быть последним where T: Значением обобщенного параметра T может быть имя класса, который является производным для указанного после двоеточия базового класса (обозначен как
    ɛɚɡɨɜɵɣ_ɤɥɚɫɫ)
    where T: Значением обобщенного параметра T может быть имя класса, реализующего данный Как все это выглядит на практике, иллюстрируют следующие примеры. В листинге 7.11 представлена программа, в которой описан обобщенный класс с одним параметром. На этот параметр накладывается ограничение его значением может быть только класс, производный от одного из обычных классов, также описанных в программе.
    
    Листинг 7.11. Ограничения на обобщенные параметры System;
    //
    Ȼɚɡɨɜɵɣ ɤɥɚɫɫ:
    class Alpha{
    //
    ɉɨɥɟ:
    protected int code;
    //
    Ʉɨɧɫɬɪɭɤɬɨɪ:
    public Alpha(int n){
    code=n;
    }
    //
    ȼɢɪɬɭɚɥɶɧɵɣ ɦɟɬɨɞ:
    public virtual void show(){
    Console.WriteLine(
    ƎɄɥɚɫɫ Alpha: Ǝ+code);
    Обобщенные типы }
    }
    //
    ɉɪɨɢɡɜɨɞɧɵɣ ɤɥɚɫɫ:
    class Bravo:Alpha{
    //
    Ʉɨɧɫɬɪɭɤɬɨɪ:
    public Bravo(int n):base(n){}
    //
    ɉɟɪɟɨɩɪɟɞɟɥɟɧɢɟ ɦɟɬɨɞɚ:
    public override void show(){
    Console.WriteLine(
    ƎɄɥɚɫɫ Bravo: Ǝ+code);
    }
    }
    //
    ɉɪɨɢɡɜɨɞɧɵɣ ɤɥɚɫɫ:
    class Charlie:Bravo{
    //
    Ʉɨɧɫɬɪɭɤɬɨɪ:
    public Charlie(int n):base(n){}
    //
    ɉɟɪɟɨɩɪɟɞɟɥɟɧɢɟ ɦɟɬɨɞɚ:
    public override void show(){
    Console.WriteLine(
    ƎɄɥɚɫɫ Charlie: Ǝ+code);
    }
    }
    //
    Ɉɛɨɛɳɟɧɧɵɣ ɤɥɚɫɫ ɫ ɨɝɪɚɧɢɱɟɧɢɟɦ ɧɚ ɨɛɨɛɳɟɧɧɵɣ ɩɚɪɚɦɟɬɪ:
    class MyClass where T: Alpha{
    //
    ɉɨɥɟ - ɫɫɵɥɤɚ ɧɚ ɨɛɴɟɤɬ:
    public Alpha obj;
    //
    Ʉɨɧɫɬɪɭɤɬɨɪ ɨɛɨɛɳɟɧɧɨɝɨ ɤɥɚɫɫɚ:
    public MyClass(T t){
    //
    ɋɫɵɥɤɚ ɧɚ ɨɛɴɟɤɬ:
    obj=t;
    //
    ȼɵɡɨɜ ɦɟɬɨɞɚ:
    obj.show();
    }
    }
    Глава 7
    1   ...   24   25   26   27   28   29   30   31   ...   40


    написать администратору сайта