В этой главе рассматриваются также обнуляемые типы, определения частичных классов и методов, буферы фикси рованного размера. И в заключение этой главы представ лен ряд ключевых слов, не упоминавшихся в предыдущих главах. Небезопасный код
В C# разрешается писать так называемый "небезопас ный" код. В этом странном на первый взгляд утвержде нии нет на самом деле ничего необычного. Небезопасным считается не плохо написанный код, а такой код, который не может быть выполнен под полным управлением в об щеязыковой исполняющей среде (CLR). Как пояснялось в главе 1, результатом программирования на C# обычно яв ляется управляемый код. Тем не менее этот язык програм мирования допускает написание кода, который не выпол няется под полным управлением в среде CLR. Такой неу правляемый код не подчиняется тем же самым средствам управления и ограничениям, что и управляемый код, и называется он небезопасным потому, что нельзя никак проверить, не выполняет ли он какое-нибудь опасное дей ствие. Следовательно, термин небезопасный совсем не означает, что коду присущи какие-то изъяны. Это просто означает, что код может выполнять действия, которые не подлежат контролю в управляемой среде.
Если небезопасный код может вызвать осложнения, то зачем вообще создавать та кой код? Дело в том, что управляемый код не позволяет использовать указатели. Если у вас имеется некоторый опыт программирования на С или C++, то вам должно быть известно, что указатели представляют собой переменные, предназначенные для хра нения адресов других объектов, т.е. они в какой-то степени похожи на ссылки в С#. Главное отличие указателя заключается в том, что он может указывать на любую об ласть памяти, тогда как ссылка всегда указывает на объект своего типа. Но поскольку указатель способен указывать практически на любую область памяти, то существует большая вероятность его неправильного использования. Кроме того, используя ука затели, легко допустить программные ошибки. Именно поэтому указатели не под держиваются при создании управляемого кода в С#. А поскольку указатели все-таки полезны и необходимы для некоторых видов программирования (например, утилит системного уровня), в C# разрешается создавать и использовать их. Но при этом все операции с указателями должны быть помечены как небезопасные, потому что они выполняются вне управляемой среды.
В языке C# указатели объявляются и используются таким же образом, как и в C/C++. Если вы знаете, как пользоваться ими в C/C++, то вам нетрудно будет сделать это и в С#. Но не забывайте, что главное назначение C# — создание управляемого кода. А спо собность этого языка программирования поддерживать неуправляемый код следует использовать для решения лишь особого рода задач. Это, скорее, исключение, чем правило для программирования на С#. По существу, для компилирования неуправ ляемого кода следует использовать параметр компилятора /unsafe.
Указатели составляют основу небезопасного кода, поэтому мы начнем его рассмо трение именно с них. Основы применения указателей
Указатель представляет собой переменную, хранящую адрес какого-нибудь другого объекта, например другой переменной. Так, если в переменной х хранится адрес пере менной у, то говорят, что переменная х указывает на переменную у. Когда указатель указывает на переменную, то значение этой переменной может быть получено или изменено по указателю. Такие операции с указателями называют непрямой адресацией. Объявление указателя
Переменные-указатели должны быть объявлены как таковые. Ниже приведена об щая форма объявления переменной-указателя: тип* имя_переменной;
где тип обозначает соотносимый тип, который не должен быть ссылочным. Это озна чает, что в C# нельзя объявить указатель на объект определенного класса. Соотноси мый тип указателя иногда еще называют базовым. Обратите внимание на положение знака * в объявлении указателя. Он должен следовать после наименования типа. А имя_переменной обозначает конкретное имя указателя-переменной.
Обратимся к конкретному примеру. Для того чтобы сделать переменную ip указа телем на значение типа int, необходимо объявить ее следующим образом. int* ip;
А указатель типа float объявляется так, как показано ниже. float* fp;
Вообще говоря, если в операторе объявления после имени типа следует знак *, то это означает, что создается переменная типа указателя.
Тип данных, на которые будет указывать сам указатель, зависит от его соотносимого типа. Поэтому в приведенных выше примерах переменная ip может служить для ука зания на значение типа int, а переменная fp — для указания на значение типа float. Следует, однако, иметь в виду, что указателю ничто не мешает указывать на что угодно. Именно поэтому указатели потенциально небезопасны.
Если у вас есть опыт программирования на С/С++, то вы должны ясно понимать главное отличие в объявлении указателей в C# и C/C++. При объявлении указателя в C/C++ знак * не разделяет список переменных в объявлении. Поэтому в следующей строке кода: int* р, q;