Продемонстрировать применение поля с ключевым словом readonly.



using System;

 

class MyClass {

public static readonly int SIZE = 10;

}

 

class DemoReadOnly {

static void Main() {

int[] source = new int[MyClass.SIZE];

int[] target = new int[MyClass.SIZE];

 

Присвоить ряд значений элементам массива source,

for(int i=0; i < MyClass.SIZE; i++)

source[i] = i;

 

Foreach(int i in source)

Console.Write(i + " ");

 

Console.WriteLine();

 

Перенести обращенную копию массива source в массив target.

for(int i = MyClass.SIZE-1, j = 0; i > 0; i--, j++)

target[j] = source[i];

 

Foreach(int i in target)

Console.Write(i + " ");

 

Console.WriteLine();

// MyClass.SIZE = 100; // Ошибка!!! He подлежит изменению!

}

}

 

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

 

 

Ключевые слова const и volatile

 

Ключевое слово, или модификатор, const служит для объявления полей и локальных переменных, которые нельзя изменять. Исходные значения таких полей и переменных должны устанавливаться при их объявлении. Следовательно, переменная с модификатором const, по существу, является константой. Например, в следующей строке кода:

 

const int i = 10;

 

создается переменная i типа const и устанавливается ее значение 10. Поле типа const очень похоже на поле типа readonly, но все же между ними есть отличие. Если поле типа readonly можно устанавливать в конструкторе, то поле типа const — нельзя.

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

Этим компилятор уведомляется о том, что значение поля типа volatile следует получать всякий раз, когда к нему осуществляется доступ.

 

 

Оператор using

 

Помимо рассматривавшейся ранее директивы using, имеется вторая форма ключевого слова using в виде оператора. Ниже приведены две общие формы этого оператора:

 

using (obj) {

// использовать объект obj

}

 

using (тип obj = инициализатор) {

// использовать объект obj

}

 

где obj является выражением, в результате вычисления которого должен быть получен объект, реализующий интерфейс System.IDisposable. Этот объект определяет переменную, которая будет использоваться в блоке оператора using. В первой форме объект объявляется вне оператора using, а во второй форме — в этом операторе. По завершении блока оператора using для объекта obj вызывается метод Dispose(), определенный в интерфейсе System.IDisposable. Таким образом, оператор using предоставляет средства, необходимые для автоматической утилизации объектов, когда они больше не нужны. Не следует, однако, забывать, что оператор using применяется только к объектам, реализующим интерфейс System.IDisposable.

В приведенном ниже примере демонстрируются обе формы оператора using.

 

// Продемонстрировать применение оператора using.

using System;

using System.IO;

 

class UsingDemo {

static void Main() {

try {

StreamReader sr = new StreamReader("test.txt");

 

Использовать объект в операторе using,

using(sr) {

// ...

}

} catch(IOException exc) {

// ...

}

 

try {

Создать объект класса StreamReader в операторе using,

using(StreamReader sr2 = new StreamReader("test.txt")) {

// ...

}

} catch(IOException exc) {

// ...

}

}

}

 

В данном примере интерфейс IDisposable реализуется в классе StreamReader (посредством его базового класса TextReader). Поэтому он может использоваться в операторе using. По завершении этого оператора автоматически вызывается метод Dispose() для переменной потока, закрывая тем самым поток.

Как следует из приведенного выше примера, оператор using особенно полезен для работы с файлами, поскольку файл автоматически закрывается по завершении блока этого оператора, даже если он и завершается исключением. Таким образом, закрытие файла с помощью оператора using зачастую упрощает код обработки файлов. Разумеется, применение оператора using не ограничивается только работой с файлами. В среде .NET Framework имеется немало других ресурсов, реализующих интерфейс IDisposable. И всеми этими ресурсами можно управлять с помощью оператора using.

 

 

Ключевое слово extern

 

Ключевое слово extern находит два основных применения. Каждое из них рассматривается далее по порядку.

 

 

Объявление внешних методов

 

В первом своем применении ключевое слово extern было доступно с момента создания С#. Оно обозначает, что метод предоставляется в неуправляемом коде, который не является составной частью программы. Иными словами, метод предоставляется внешним кодом.

Для того чтобы объявить метод как внешний, достаточно указать в самом начале его объявления модификатор extern. Таким образом, общая форма объявления внешнего метода выглядит следующим образом.

 

extern возвращаемый_тип имя_метода (список_аргументов) ;

 

Обратите внимание на отсутствие фигурных скобок.

В данном варианте ключевое слово extern нередко применяется вместе с атрибутом DllImport, обозначающим библиотеку DLL, в которой содержится внешний метод. Атрибут DllImport принадлежит пространству имен System.Runtime.InteropServices. Он допускает несколько вариантов, но, как правило, достаточно указать лишь имя библиотеки DLL, в которой содержится внешний метод. Вообще говоря, внешние методы следует программировать на С. (Если же это делается на C++, то имя внешнего метода может быть изменено в библиотеке DLL путем дополнительного оформления типов.)

Для того чтобы стало понятнее, как пользоваться внешними методами, обратимся к примеру конкретной программы, состоящей из двух файлов. Ниже приведен исходный код С из первого файла ExtMeth.с, где определяется метод AbsMax().

 

#include <stdlib.h>

int __declspec(dllexport) AbsMax(int a, int b) {

return abs(a) < abs(b) ? abs(b) : abs(a);

}

 

В методе AbsMax() сравниваются абсолютные значения двух его параметров и возвращается самое большое из них. Обратите внимание на обозначение __declspec(dllexport). Это специальное расширение языка С для программных средств корпорации Microsoft. Оно уведомляет компилятор о необходимости экспортировать метод AbsMax() из библиотеки DLL, в которой он содержится. Для компилирования файла ExtMeth.с в командной строке указывается следующее.

 

CL /LD /MD ExtMeth.с

 

В итоге создается библиотечный файл DLL — ExtMeth .dll.

Далее следует программа на С#, в которой применяется внешний метод AbsMax().

 

using System;

using System.Runtime.InteropServices;

class ExternMeth {


Дата добавления: 2019-02-12; просмотров: 268; Мы поможем в написании вашей работы!

Поделиться с друзьями:






Мы поможем в написании ваших работ!