4 сем Инфа готово

20 Февраль 2014 →

Вопрос 1 – ILASM,ILDASM,Reflecrion, устройство сборок

•Ассемблер MSIL (ilasm.exe).

Позволяет превратить текстовый файл с кодом на MSIL в PE-файл (EXE или DLL), который будет выполняться при наличии совместимой версии .NET Framework.

•ДизассемблерMSIL (ildasm.exe). Используется для дизассемблирования и просмотра MSIL-кода, содержащегося в PE-файле.

Дисассемблер промежуточного языка Microsoft ILDASM (Microsoft Intermediate Language Disassembler) может отображать метаданные и инструкции языка MSIL, связанные с соответствующим .NET-кодом. Дисассемблер ILDASM является очень полезной утилитой, которая используется при отладке приложений. Он позволяет более глубоко понять инфраструктуру платформы .NET. Кроме того, дисассемблер промежуточного языка Microsoft ILDASM можно использовать для изучения кода библиотеки классов .NET Framework [Дисассемблер ILDASM можно найти в меню Tools (Сервис) Visual Studio.NET. Одна из таких утилит - ILDASM, входящая в состав Microsoft .NET Framework. Данная утилита может использоваться не только для просмотра метаданных, но и для изучения кода на промежуточном языке (IL) в том или ином файле (в файле с расширением .EXE или .DLL,

Отражение (reflection) — это средство С#, которое позволяет получить информацию о типе. Термин отражение произошел от характера процесса: объект класса Туре воспроизводит, или отражает, базовый тип, который он представляет. Для получения интересующей вас информации вы "задаете вопросы" объекту класса Туре, а он возвращает (отражает) для вас информацию, связанную с этим типом. Отражение — мощный механизм, позволяющий узнать характеристики типа, точное имя которого становится известным только во время выполнения программы, и соответствующим образом использовать их. Многие классы, которые поддерживают средство отражения, являются частью интерфейса .NET Reflection API, который определен в пространстве имен System.Reflection. Таким образом, в программы, которые используют средство отражения, обычно включается следующая инструкция: using System.Reflection;

.NET Reflector — бесплатная утилита для Microsoft .NET, комбинирующая браузер классов, статический анализатор и декомпилятор, изначально написанная Lutz Roeder.

Программа может использоваться для навигации, поиска и анализа содержимого .NET-компонентов, а также сборок и переводить двоичные данные в форму, пригодную для чтения человеком. Reflector позволяет производить декомпиляцию .NET-сборок на языки C#, Visual Basic .NET и MSIL. Reflector также включает дерево вызовов (англ. Call Tree), которое может использоваться для навигации вглубь IL-методов с целью определения, какие методы они вызывают. Программа отображает метаданные, ресурсы и XML-документацию. .NET Reflector может быть использован .NET-разработчиками для понимания внутренней работы библиотек кода, для наглядного отображения различий между двумя версиями сборки, и того, как различные части .NET-приложения взаимодействуют друг с другом..NET Reflector может использоваться для нахождения мест, имеющих проблемы с производительностью и поиска багов. Он также может быть использован для поиска зависимостей сборки. Программа может быть использована для эффективной конвертации кода между C# и VB.NET.

Сборка (assembly) - это полностью самодостаточный и, скорее, логический, нежели физический элемент. Это значит, что он может быть сохранен в более чем одном файле (хотя динамические сборки хранятся в памяти, а вовсе не в файлах). Если сборка хранится в более чем одном файле, то должны быть один главный файл, содержащий точку входа и описывающий остальные файлы. Важное свойство сборок состоит в том, что они содержат метаданные, описывающие типы и методы, определенные в ее коде. Помимо этого сборка хранит в себе метаданные описывающие ее саму. Эти метаданные, хранимые в области манифеста, позволяют выполнить проверку номера версии сборки и ее целостность. Манифест - часть сборки, декларирующая метаданные , то есть описывающая сборку и параметры для ее использования. Если сборка состоит из одного файла, манифест встраивается в PE (portable executable) код, формируя однофайловую сборку. Если же сборка не ограничена одним фалом, то вы можете как включить манифест в один из файлов с PE кодом, так и разместить его в отдельном файле.Среда выполнения выполняет программный код, только если с ним ассоциировани манифест. Сборка может иметь только одну точку входа (Main, WinMain, DllMain). Сборка представляет собой коллекцию из одного или более файлов.Такие сборки называются статическими сборками, поскольку они хранятся на диске. Динамические сборки создаются во время выполнения программы и на диске обычно не сохраняются.

C MSDN :

Сборки являются структурными элементами приложений .NET Framework; они составляют основную единицу развертывания, управления версиями, повторного использования, областей действия активации и разрешений безопасности. Сборка представляет собой коллекцию типов и ресурсов, собранных для совместной работы и образующих логическую функциональную единицу. Сборка предоставляет среде CLR сведения, необходимые для распознавания реализаций типов. Для среды выполнения тип не существует вне контекста сборки.

Вопрос 2. Архитектура платформы .NET. Основные компоненты платформы.

.NET платформа упрощает разработку приложений и повышает надежность кода. В частности, она обеспечивает автоматическое управление временем жизни объектов, нейтральные к языкам библиотеки классов и пересекающие границы языков наследование, обработку исключений и отладку.

Архитектура .NET изображена на рисунке. Основные компоненты.

1) Основное назначение Common Language Runtime (CLR) - выполнение приложений, управление выполнением кода, написанного на любом современном языке программирования, соблюдение всех программных зависимостей, управление памятью, обеспечение безопасности, интеграция с языками программирования и т.п. Среда выполнения обеспечивает множество сервисов, облегчающих создание и внедрение приложений, и существенно улучшает надежность последних.

2) Common Language Runtime и базовые классы вместе составляют основу .NET платформы.

Разработчики не взаимодействуют с Common Language Runtime напрямую - все сервисы предоставляются унифицированной библиотекой классов, которая располагается над CLR. Эта библиотека содержит более 1000 классов для решения различных программных задач - от взаимодействия с сервисами операционной системы до работы с данными и XML-документами. Частью указанной библиотеки классов является программная модель для создания Web-приложений, называемая ASP.NET. Она модель содержит классы, компоненты и сервисы, облегчающие создание Web-сервисов и приложений. Отметим, что помимо Web-сервисов и Web-приложений с помощью Microsoft .NET Framework можно создавать и другие типы приложений - консольные приложения, приложения на основе Windows Forms и Windows-сервисы. Но поскольку основной задачей Microsoft .NET Framework является поддержка создания Web-приложений, именно компонент ASP.NET играет наиболее значительную роль в архитектуре Microsoft .NET Framework.

.NET предлагает также высокоуровневые сервисы: ADO+ - новое поколение ADO, которое использует XML и SOAP для обмена данными

3) На самом нижнем уровне нашей диаграммы располагаются сервисы операционной системы. Сервисы платформы Windows обеспечивают поддержку таких технологий, как COM+, а также управление транзакциями, очередями сообщений и т.п.

4) Под Common Language Specification (или CLS) понимается набор правил, определяющих подмножество обобщенных типов данных, в отношении которых гарантируется, что они безопасны при использовании во всех языках .NET.

Вопрос 3. Выполнение приложений на платформе Microsoft .NET.

Common Language Runtime обеспечивает среду выполнения .NET-приложений. Среди предоставляемых этой средой функций следует отметить обработку исключительных ситуаций, обеспечение безопасности, средства отладки поддержки версий. Все эти функции доступны из любого языка программирования, соответствующего спецификации Common Language Specification. Microsoft предоставляет три языка программирования, способных использовать CLR, - Visual Basic .NET, Visual C# .NET и Visual C++ With Managed Extensions.

Компилируемый компилятором код для CLR называется управляемым кодом (managed code). Управляемый код пользуется преимуществами среды выполнения и помимо собственно кода содержит метаданные, которые создаются в процессе компиляции и содержат информацию о типах, членах и ссылках, используемых в коде. Метаданные используются средой выполнения:

1)для обнаружения классов;

2)загрузки классов;

3)генерации кода для конкретной платформы;

4)обеспечения безопасности.

Среда выполнения также следит за временем жизни объектов. В CLR используются счетчики, а удаление объектов из памяти происходит с помощью процесса, называемого сборкой мусора (garbage collection).

CLR также задает общую систему типов, используемую всеми языками программирования. Это означает, например, что все языки программирования будут оперировать целочисленными данными или данными с плавающей точкой единого формата и единой длины, а представления строк тоже будут едиными для всех языков программирования. За счет единой системы типов достигается более простая интеграция компонентов и кода, написанных на разных языках программирования. В отличие от COM-технологии, также основанной на наборе стандартных типов, но представляемых в бинарном виде, CLR позволяет выполнять интеграцию кода (который может быть написан на различных языках программирования) в режиме дизайна, а не в режиме выполнения.

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

Вопрос 4. Компиляция и выполнение приложений на платформе Microsoft .NET.

Все CLR-совместимые компиляторы вместо этого генерируют IL-код, который также называется управляемым модулем, потому что CLR управляет его жизненным циклом и выполнением. Рассмотрим составные части управляемого модуля:

Заголовок PE32 или PE32+: Файл с заголовком в формате PE32 может выполняться в 32- или 64-разрядной ОС, а с заголовком PE32+ только в 64-разрядной ОС. Заголовок показывает тип файла: GUI, CUI или DLL, он также имеет временную метку, показывающую, когда файл был собран. Для модулей, содержащих только IL-код, основной объем информации в РЕ-заголовке игнорируется, Для модулей, содержащих процессорный код, этот заголовок содержит сведения о процессорном коде.

Заголовок CLR: Содержит информацию, которая превращает этот модуль в управляемый. Заголовок включает нужную версию СLR, некоторые флаги, метку метаданных, точки входа в управляемый модуль (метод Main), месторасположение и размер метаданных модуля, ресурсов и т.д.

Метаданные - это набор таблиц данных, описывающих то, что определено в модуле. Есть два основных вида таблиц: описывающие типы и члены, определенные в вашем исходном коде, и описывающие типы и члены, на которые имеются ссылки в вашем исходном коде. Метаданные служат многим целям:

1)устраняют необходимость в заголовочных и библиотечных файлах при компиляции, так как все сведения о типах и членах, на которые есть ссылки, содержатся в файле с IL-кодом, в котором они реализованы. Компиляторы могут читать метаданные прямо из управляемых модулей.

2)при компиляции IL-кода в машинный код CLR выполняет верификацию (проверку "безопасности" выполнения кода) используя метаданные, например, нужное ли число параметров передается методу, корректны ли их типы, правильно ли используется возвращаемое значение и т.д.

3)позволяют сборщику мусора отслеживать жизненный цикл объектов и т.д.

IL-код: управляемый код, создаваемый компилятором при компиляции исходного кода. Во время исполнения CLR компилирует IL-код в команды процессора.

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

Чтобы понять принцип выполнения программы в среде CLR рассмотрим небольшой пример:

Непосредственно перед исполнением функции Main CLR находит все типы, на которые ссылается ее код. В нашем случае метод Main ссылается на единственный тип — Console, и CLR выделяет единственную внутреннюю структуру WriteLine.

Когда Main первый раз обращается к WriteLine, вызывается функция JITCompiler (условное название), которая отвечает за компиляцию IL-кода вызываемого метода в собственные команды процессора. Функции JITCompiler известен вызываемый метод и тип, в котором он определен. JITCompiler ищет в метаданных соответствующей сборки IL-код вызываемого метода, затем проверяет и компилирует IL-код в собственные команды процессора, которые сохраняются в динамически выделенном блоке памяти. После этого JITCompiler возвращается к внутренней структуре данных типа и заменяет адрес вызываемого метода адресом блока памяти, содержащего собственные команды процессора. В завершение JITCompiler передает управление коду в этом блоке памяти. Далее управление возвращается в Main, который продолжает работу в обычном порядке.

Затем Main обращается к WriteLine вторично. К этому моменту код WriteLine уже проверен и скомпилирован, так что производится обращение к блоку памяти, минуя вызов JITCompiler. Отработав, метод WriteLine возвращает управление Main.

Таким образом, за счет такой компиляции производительность теряется только при первом вызове метода. Все последующие обращения к одной и той же структуре выполняются "на полной скорости", без повторной верификации и компиляции.

Промежуточный Язык и JIT компилятор

MSIL – это процессоронезависимый промежуточный язык, созданный Microsoft. MSIL - язык более высокого уровня, чем большинство машинных языков. Он понимает типы объектов и имеет инструкции для создания и инициализации объектов, вызова виртуальных методы и непосредственной манипуляции элементами массива. Он даже имеет инструкции, которые оперируют исключениями. Как и любой другой машинный язык, MSIL может быть написан на ассемблере. Microsoft предоставляет ассемблер и дизассемблер для MSIL.

Перед тем, как выполнять управляемый код CLR должен сначала скомпилировать управляемые MSIL инструкции в инструкции процессора. Здесь возникает типичная проблема: когда пользователь запускает программу, он не намерен ждать пока вся программа скомпилируется, тем более, что большинство функций программы не будут вызваны. Поэтому CLR, компилирует MSIL код в инструкции процессора, когда функции непосредственно вызваны. Всякий раз, когда такая функция вызывается в будущем, сразу выполняется машинный код (а компилятор уже не вовлекается в процесс). Поскольку MSIL компилируется только в нужный момент (just-in-time - JIT), этот компонент CLR часто упоминается как JIT компилятор (JIT compiler) или JITter.

(Перевод: исходный код-> компилятор -> exe/dll (IL и метаданные) –> загрузчик класса -> JIT компилятор с необязательной проверкой -> машинные коды -> выполнение -> проверки безопасности; runtime engine; Библиотеки класов (IL и метаданные); безопасный прекомпилированный код; вызов некомпилированного метода)

Вопрос 5. Атрибуты

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

Все атрибуты (в отличие, скажем, от атрибутов языка IDL) являются классами (потомками класса System.Attribute). В отличие от атрибутов IDL набор атрибутов .NET открыт для дополнения, т. е. вы можете определять собственные атрибуты и применять их к вышеуказанным элементам вашего кода.

Атрибуты делятся на предопределенные (встроенные) и пользовательские (которые пишет программист).

Встроенные атрибуты могут использоваться, например, при сериализации (сохранении в поток) данных класса. Скажем, вам надо, чтобы у класса сохранялись не все данные - в этом случае вы можете пометить те данные, которые не надо сохранять, специальным атрибутом.

Еще пример применения атрибутов. Компоненты, которые вы располагаете на форме (кнопки, метки и т. п.) имеют некоторый набор свойств (шрифт, местоположение, видимость и т. п.). В IDE Visual Studio вы можете выбрать в окне Properties один из двух способов расположения этих свойств - по алфавиту или по категориям. Так вот, в какую категорию попадет то или иное свойство, определяется специальным встроенным атрибутом.

Атрибуты в C# заключаются в квадратные скобки.

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

using System;

namespace test

{

//Объявление атрибута.

[AttributeUsage(AttributeTargets.All, Inherited = false, AllowMultiple = true)]

class TestAttribute: System.Attribute

{

//Поле атрибута.

private string name;

//Конструктор атрибута.

public TestAttribute(string name)

{

this.name = name;

}

//Свойство только для чтения.

public virtual string Name

{get

{ return name;

}}}

//Конец объявления атрибута.

//Применение атрибута к классу.

[TestAttribute("NAME")]

class Test

{

static void Main()

{

GetAttribute(typeof(Test));

}

public static void GetAttribute(Type t)

{

TestAttribute att=

(TestAttribute) Attribute.GetCustomAttribute(t, typeof(TestAttribute));

Console.WriteLine("{0}", att.Name);

}

}

}

Как видно, атрибут TestAttribute является потомком класса System.Attribute. Перед определением нового атрибута мы видим строку

[AttributeUsage(AttributeTargets.All, Inherited = false, AllowMultiple = true)]

Этой строкой определяется область применения нашего атрибута - первый параметр (AttributeTargets.All) говорит о том, что мы сможем применять наш атрибут TestAttribute к чему угодно, второй (Inherited=false) - что атрибут не будет наследоваться (т. е. если мы применим атрибут TestAttribute к некоторому классу, то у потомков этого класса атрибута TestAttribute не будет), третий (AllowMultiple = true) - что атрибут к каждому элементу может пременяться только один раз (заметим в скобках, что для определения области применения нашего пользовательского атрибута мы используем другой атрибут - AttributeUsage).

Далее мы определяем для нашего атрибута внутреннюю переменную name типа string и конструктор с параметром типа string. В конструкторе мы записываем значение в переменную name. Еще чуть ниже мы пишем в классе атрибута свойство только для чтения:

public virtual string Name

{ get

{ return name;

} }

После создания класса атрибута мы применяем его к другому классу Test. Для этого мы должны создать экземпляр атрибута TestAttribute непосредственно перед классом Test:

[TestAttribute("NAME")]

class Test

{

Делаем мы это в квадратных скобках. При этом у нас вызывается конструктор с параметром атрибута.

В классе Test мы в методе GetAttribute просто выводим на консоль значение свойства name атрибута. Для этого мы воспользовались статическим методом GetCustomAttribute класса Attribute. Этот метод принимает в качестве параметров тип, к которому атрибут применяется (т. е. класс Test в нашем случае) и собственно атрибут, который мы применяем (у нас это TestAttribute). Возвращает же он экземпляр атрибута, который мы и используем для получения значения свойства name.

Метод GetAttribute мы вызываем в констукторе класса Test.

Результатом выполнения нашей программы будет вывод на консоль слова "NAME".

Вопрос 6. Net.Framework

Библиотека классов .NET Framework состоит из пространств имен. Каждое пространство имен содержит типы, которые можно использовать в программах: классы, структуры, перечисления, делегаты и интерфейсы. Обзор пространств имен см. в разделе Библиотека классов.

Пространства имен обеспечивают ограничение области видимости: два класса с одним и тем же именем могут быть использованы в программе постольку, поскольку они находятся в разных пространствах имен и их имена определены в рамках соответствующих пространств имен. Имя пространства имен является частью полного имени типа (namespace.typename).

Названия всех пространств имен, созданных корпорацией Майкрософт, начинаются с одного из двух имен: System или Microsoft.

Управляемые библиотеки DLL (сборки)

Функциональность платформы .NET Framework не концентрируется в одиночной библиотеке DLL. Благодаря распределению функциональных возможностей базовых классов по нескольким библиотекам DLL управляемой программе не нужно загружать во время запуска большую библиотеку DLL; вместо этого загружается одна или несколько небольших библиотек DLL. Это позволяет уменьшить время запуска программы.

Можно также использовать пространства имен, определенные в проекте. Однако, как правило, используются типы из пространств имен, находящихся в управляемых библиотеках DLL. Управляемые библиотеки DLL также называются сборками.

При создании проекта Visual Basic или Visual C# в Visual Studio ссылки на наиболее часто используемые библиотеки DLL (сборки), содержащие базовые классы, добавляются автоматически. Тем не менее, если необходимо использовать тип, находящийся в библиотеке DLL, ссылка на которую отсутствует, потребуется добавить ссылку на нее. Для добавления сборок служит диалоговое окно Добавление ссылки.

Сборки являются структурными элементами приложений .NET Framework; они составляют основную единицу развертывания, управления версиями, повторного использования, областей действия активации и разрешений безопасности. Сборка представляет собой коллекцию типов и ресурсов, собранных для совместной работы и образующих логическую функциональную единицу. Сборка предоставляет среде CLR сведения, необходимые для распознавания реализаций типов. Для среды выполнения тип не существует вне контекста сборки.

Вопрос 7. Библиотеки System.IO.

В следующей таблице перечислены классы, обычно используемые для файлового ввода-вывода в .NET Framework. Они разделены на классы файлового ввода-вывода, классы для создания потоков и классы для чтения и записи в поток.

Документацию по .NET Framework 2.0 и более полный список см. в разделе Общие сведения о библиотеке классов .NET Framework.

Основные классы ввода-вывода для файлов, каталогов и дисков

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

System.IO.Directory

Предоставляет статические методы для создания, перемещения и перечисления в каталогах и вложенных каталогах.

System.IO.DirectoryInfo

Предоставляет методы экземпляра класса для создания, перемещения и перечисления в каталогах и вложенных каталогах.

System.IO.DriveInfo

Предоставляет методы экземпляра класса для создания, перемещения и перечисления по дискам.

System.IO.File

Предоставляет статические методы для создания, копирования, удаления, перемещения и открытия файлов, а также помогает при создании объектов FileStream.

System.IO.FileAccess

Определяет константы чтения, записи или чтения и записи файла.

System.IO.FileAttributes

Предоставляет атрибуты для файлов и каталогов, например ArchiveHidden и ReadOnly.

System.IO.FileInfo

Предоставляет статические методы для создания, копирования, удаления, перемещения и открытия файлов, а также помогает при создании объектов FileStream.

System.IO.FileMode

Управляет процессом открытия файла. Этот параметр задается во многих конструкторах объектов FileStream и IsolatedStorageFileStream и методах Open объектов File и FileInfo.

System.IO.FileShare

Определяет константы для управления типом доступа других файловых потоков к этому же файлу.

System.IO.Path

Предоставляет методы и свойства для обработки строк каталога.

System.Security.Permissions.FileIOPermission

Управляет доступом к файлам и каталогам путем определения разрешений Read, WriteAppend и PathDiscovery.

Классы, используемые для создания потоков

В следующей таблице перечислены и описаны основные классы, используемые для создания потоков.

System.IO.BufferedStream

Осуществляет буферизацию в операциях чтения и записи в другие потоки.

System.IO.FileStream

Поддерживает произвольный доступ к файлам с помощью метода Seek. Класс FileStream по умолчанию открывает файлы для синхронного доступа, но также поддерживает и асинхронные операции.

{// Set the stream position to the beginning of the file.

fileStream.Seek(0, SeekOrigin.Begin);} пример

System.IO.MemoryStream

Создает поток, резервное хранилище которого находится в памяти, а не в файле.

System.Net.Sockets.NetworkStream

Обеспечивает базовый поток данных для доступа к сети.

System.Security.Cryptography.CryptoStream

Определяет поток, который связывает потоки данных с криптографическими преобразованиями.

Классы, используемые для чтения и записи в потоки

В следующей таблице описаны некоторые классы, используемые для чтения и записи в файлы с помощью потоков.

System.IO.BinaryReader

Считывает кодированные строки и простые типы данных из FileStream.

System.IO.BinaryWriter

Записывает кодированные строки и простые типы данных в FileStream.

System.IO.StreamReader

Считывает символы из FileStream, используя кодировку CurrentEncoding для преобразования символов в байты и обратно. Класс StreamReader имеет конструктор, в котором делается попытка установить правильную кодировку CurrentEncoding для данного потока на основе наличия типичного для кодировки CurrentEncoding заголовка, такого как метка порядка байтов.

System.IO.StreamWriter

Записывает символы в поток FileStream, используя класс Encoding для преобразования символов в байты.

System.IO.StringReader

Считывает символы из String. Вывод может быть либо потоком в любой кодировке, либо String.

System.IO.StringWriter

Записывает символы в String. Вывод может быть либо потоком в любой кодировке, либо String.

StreamReader разработан для ввода символов в определенной кодировке, тогда как класс Stream разработан для ввода и вывода байтов. StreamReader служит для чтения строк данных из стандартного текстового файла. StreamWriter разработан для вывода символов в определенной кодировке, тогда как классы, производные от Stream, разработаны для ввода и вывода байтов.

Класс Stream является абстрактным базовым классом всех потоков. Поток — это абстракция последовательности байтов, например файл, устройство ввода-вывода, канал взаимодействия процессов или сокет TCP/IP. Класс Stream и его производные классы предоставляют универсальное представление различных типов ввода и вывода, изолируя программиста от отдельных сведений операционной системы и базовых устройств.

Используйте класс FileStream для операций чтения и записи в файл, открытия и закрытия файлов в файловой системе, а также для изменения других дескрипторов операционной системы для обработки файлов, включая каналы, стандартный ввод и вывод. Можно задать синхронное или асинхронное выполнение операций чтения и записи. Для достижения лучшей производительности FileStream буферизирует ввод и вывод.

Объекты FileStream поддерживают произвольный доступ к файлам с использованием метода Seek. Seek позволяет перемещать положение чтения и записи в любое место внутри файла. Это осуществляется путем смещения параметров точки ссылки. Смещение в байтах относительно точки ссылки поиска, которая может располагаться в начале, в текущем положении или в конце файла, определяется тремя свойствами класса SeekOrigin.

Вопрос 8. Взаимодействие с неуправляемым кодом

Как вы, наверное, догадались, неуправляемым (unmanaged code) называется код, который не находится под надзором .NET. Поясним: этот код тоже запускается средствами .NET. Однако у неуправляемого кода нет тех преимуществ, которыми обладает управляемый: сбора мусора, унифицированной системы типов и метаданных. Вы спрашиваете, зачем запускать неуправляемый код в среде .NET? Правильно, без особой нужды этого делать не стоит. Однако вы пойдете на это, когда у вас не будет другого выхода. Вот несколько ситуаций, которые показывают, что можно поблагодарить Microsoft за то, что в .NET заложена эта особенность.

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

Управляемый код, использующий компоненты СОМ По той же причине, по какой нужно вызывать из своего .NET-приложения функции из DLL, написанной на С, вам требуется продолжать поддержку компонентов СОМ. Выход в том, чтобы создать .NET-оболочку для компонента СОМ так, чтобы управляемый клиент полагал, будто он работает с .NET-классом.

Неуправляемый код, использующий .NET-службы Здесь противоположная проблема: вам нужен доступ к .NET из неуправляемого кода. Она решается с помощью обратного подхода: клиент СОМ вводится в заблуждение, будто он работает с СОМ-сервером, который на самом деле является .NET-службой того же вида.

С# позволяет программистам писать то, что называется "опасный кодом" (unsafe code). Опасный код — это код, который не плохо написан, а код, который не выполняется под полным управлением системы Common Language Runtime (CLR). С этой точки зрения весь код на CC++ "опасен". Нет проверок на границы массива, нет автоосвобождени памяти и так далее. Язык С# обычно используется для создания управляемого кода. Однако можно написать и "неуправляемый" код, который не подчиняется тем же средствам управления и ограничениям, налагаемым на управляемый код. Такой код называется "опасным", поскольку невозможно проконтролировать невыполнение им опасных действий. Таким образом, термин опасный не означает, что коду присуща некорректность. Он просто означает возможность выполнения действий, которые не являются предметом управления системы CLR.

Основное различие между указателями в CC++ и ссылками в C# заключается в том, что указатель может указывать на что угодно в памяти, а ссылка всегда указывает на объект "своего" типа.

Но если указатель может указывать на что угодно, возможно неправильное его использование. Кроме того, работая с указателями, можно легко внести в код ошибку, которую будет трудно отыскать. Вот почему С# не поддерживает указатели при создании управляемого кода. Теме не менее указатели существуют, причем для некоторых типов программ (например, системных утилит) они не просто полезны, они — необходимы, и С# позволяет (что поделаешь) программистам создавать их и использовать. Однако все операции с указателями должны быть отмечены как "опасные", поскольку они выполняются вне управляемого контекста. Объявление и использование указателей в С# происходит аналогично тому, как это делается в C/C++ (если вы знаете, как использовать указатели в C/C++, можете так же работать с ними и в С#). Но помните: особенность С# — создание управляемого кода. Его способность поддерживать неуправляемый код позволяет применять Сопрограммы к задачам специальной категории. Но такое С#- рограммирование уже не попадает под определение стандартного. И в самом деле, чтобы скомпилировать неуправляемый код, необходимо использовать опцию компилятора /unsafe.

Создаём проект, заходим в свойства нашего ConsoleApplication, там кликаем вкладку Build, и выбираем галку Allow unsafe code

Пример:

// Демонстрация использования указателей и

// ключевого слова unsafe.

using System;

class UnsafeCode

{

// Отмечаем метод Main() как "опасный",

unsafe public static void Main()



Страницы: Первая | 1 | 2 | 3 | ... | Следующая → | Последняя | Одной страницей


See also:
Для студента
Похожие записи

Комментарии закрыты.