Поиск

Приведение типов

Сейчас мы рассмотрим один из самых важных аспектов типов — приведение. Допустим, существует базовый класс под названием Employee и производный класс ContractEmployee. Следующий код будет работать, поскольку всегда подразумевается восходящее приведение (upcast) производного класса к его базовому классу:

class Employee { }
class ContractEmployee : Employee { }
class CastExamplel
{
public static void Main () {
Employee e = new ContractEmployeeQ; } }

А вот такой код недопустим, так как компилятор не предоставляет неявное нисходящее приведение (downcast).

class Employee { }
class ContractEmployee : Employee { }
class CastExample2 {
public static void Main ()
{
ContractEmployee ce = new EmployeeQ; // He будет
// компилироваться.
} }

Причина различного поведения этих фрагментов кода, описанная в главе 1, связана с понятием заменяемости (substitutability). Правила заменяемости гласят: производный класс может быть использован вместо своего базового класса. Поэтому объект типа ContractEmployee всегда можно использовать вместо объекта Employee. Потому и компилируется код первого примера.

Однако вы не сможете выполнить нисходящее приведение объекта типа Employee к объекту типа ContractEmployee, поскольку нет гарантии, что этот объект поддерживает интерфейс, определенный классом ContractEmployee. Поэтому в случае нисходящего приведения используется явное приведение:

class Employee { }
class ContractEmployee : Employee { }
class CastExampleS {
public static void Main ()
{
// Нисходящее приведение не сработает.
ContractEmployee ce = (ContractEmployee)new Employee(); } }

А давайте обманем CTS путем явного приведения базового класса к производному:

class Employee { }
class ContractEmployee : Employee { }
class CastExample4 {
public static void Main ()
<
Employee e = new EmployeeO; ContractEmployee с = (ContractEmployee)e; } }

Эта программа компилируется, но генерирует исключение периода выполнения. Здесь важны два момента. Во-первых, ошибка периода компиляции не возникает, так как е на самом деле может быть объектом ContractEmployee, приведенным к базовому классу. Поэтому истинная природа объекта, приведенного к базовому классу, не может быть распознана до периода выполнения. Во-вторых, CLR определяет типы объектов в период выполнения. Распознав неверное приведение, CLR генерирует исключение System.InvalidCastException.

Есть еще один способ приведения объектов — ключевое слово «5. Преимущество использования as вместо собственно приведения в том, что в случае неверного приведения вам не придется беспокоиться о возникающем исключении. Вместо этого вы получите null, например:

using System;
class Employee { >
class ContractEmployee : Employee { }
class CastExampleS {
public static void Main ()
{
Employee e = new EmployeeO;
Console.WriteLine("e = {0}",
e == null ? "null" : e.ToStringO);
ContractEmployee с = e as ContractEmployee; Console.WriteLine("c = {0}",
с == null ? "null" : e.ToStringO); > }
Запустив этот пример, вы увидите такой результат:
c:>CastExample5 e = Employee с = null

Способность сравнивать объект с null означает, что вы ничем не рискуете, используя пустые объекты. Фактически, если в приведенном выше примере вызвать метод System.Object для объекта с, то CTS сгенерирует исключение System.NullReferenceException.

Пространства имен

Пространства имен (namespaces) используются в С#-приложениях для определения области видимости. Объявив пространство имен, разработчик может дать С#-приложению иерархическую структуру, основанную на семантически связанных группах типов и других (вложенных) пространствах имен. В формировании одного пространства имен могут участвовать несколько файлов исходного кода. Это обстоятельство позволяет при компоновке единого пространства имен из нескольких классов определять каждый класс в собственном файле исходного кода. Программист, использующий созданные вами классы, получит доступ ко всем классам в пространстве имен через ключевое слово using.

ПРИМЕЧАНИЕ Там, где это возможно, рекомендуется использовать имя компании в качестве корня пространства имен, чтобы гарантировать его уникальность.