В приведенном ниже простом примере демонстрируется механизм наложения ограничения на базовый класс. // Простой пример, демонстрирующий механизм наложения // ограничения на базовый класс. using System; class А { public void Hello { Console.WriteLine("Hello"); } } // Класс В наследует класс А. class В : А { } // Класс С не наследует класс А. class С { } // В силу ограничения на базовый класс во всех аргументах типа, // передаваемых классу Test, должен присутствовать базовый класс А. class Test where Т : А { Т obj; public Test(Т о) { obj = о; } public void SayHello { // Метод Hello вызывается, поскольку он объявлен в базовом классе А. obj.Hello; } } class BaseClassConstraintDemo { static void Main { A a = new A; В b = new В; С с = new С; // Следующий код вполне допустим, поскольку класс А указан как базовый. Test t1 = new Test(a); t1.SayHello; // Следующий код вполне допустим, поскольку класс В наследует от класса А. Test t2 = new Test(b); t2.SayHello; // Следующий код недопустим, поскольку класс С не наследует от класса А. // Test t3 = new Test(c); // Ошибка! // t3.SayHello; // Ошибка! } }

В данном примере кода класс А наследуется классом В, но не наследуется классом С. Обратите также внимание на то, что в классе А объявляется метод Hello, а класс Test объявляется как обобщенный следующим образом. class Test where Т : А {

Оператор where в этом объявлении накладывает следующее ограничение: любой аргумент, указываемый для типа Т, должен иметь класс А в качестве базового.

А теперь обратите внимание на то, что в классе Test объявляется метод SayHello, как показано ниже. public void SayHello { // Метод Hello вызывается, поскольку он объявлен в базовом классе А. obj.Hello; }

Этот метод вызывает в свою очередь метод Hello для объекта obj типа Т. Любо пытно, что единственным основанием для вызова метода Hello служит следующее требование ограничения на базовый класс: любой аргумент типа, привязанный к типу Т, должен относиться к классу А или наследовать от класса А, в котором объявлен ме тод Hello. Следовательно, любой допустимый тип Т будет также определять метод Hello. Если бы данное ограничение на базовый класс не было наложено, то компи лятору ничего не было бы известно о том, что метод Hello может быть вызван для объекта типа Т. Убедитесь в этом сами, удалив оператор where из объявления обоб щенного класса Test. В этом случае программа не подлежит компиляции, поскольку теперь метод Hello неизвестен.

Помимо разрешения доступа к членам базового класса, ограничение на базовый класс гарантирует, что в качестве аргументов типа могут быть переданы только те типы данных, которые наследуют базовый класс. Именно поэтому приведенные ниже стро ки кода закомментированы. // Test t3 = new Test(c); // Ошибка! // t3.SayHello; // Ошибка!

Класс С не наследует от класса А, и поэтому он не может использоваться в качестве аргумента типа при создании объекта типа Test. Убедитесь в этом сами, удалив сим волы комментария и попытавшись перекомпилировать этот код.

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

Перейти на страницу:

Похожие книги