public class Plant: IfruitHaver {

 [System.Runtime.InteropServices.DllImport('User32.dll)]

 public static extern int See();

 public Plant(){}

 public void Fruit() {

  Console.WriteLine('Generic plant fruit');

 }

}

Здесь метод See() помечен как статический. Атрибут DllImport требует этого от методов, на которых он используется

Пока не существует версии C# ключевых слов transient, volatile или synchronized. Однако существует ряд способов, предоставляемых SDK .NET для имитации некоторой их функциональности. C# использует атрибут NonSerialized, связанный с полями класса, для предоставления механизма, аналогичного по функциональности модификатору Java transient, этот атрибут однако опротестован, поэтому может быть изменен в будущих версиях.

Синхронизация в C# несколько усложнена (более трудоемка) по сравнению с ее аналогом в Java. В общем, любой поток выполнения может по умолчанию получить доступ ко всем членам объекта. Имеется, однако ряд способов синхронизации кода в зависимости от потребностей разработчика с помощью использования таких средств, как Monitors. Они предоставляют возможность делать и освобождать блокировки синхронизации на объектах SyncBlocks, которые содержат блокировку используемую для реализации синхронизированных методов и блоков кода; список ожидающих потоков выполнения, используемых для реализации функциональности монитора ReaderWriterLock, который определяет образец одного писателя для многочисленных читателей; примитивы синхронизации Mutex, предоставляющие межпроцессную синхронизацию; и System.Threading.Interlocked, который может использоваться для предоставлении синхронизированного доступа к переменным через несколько потоков выполнения.

Первый шаг к синхронизации в C# состоит в ссылке на сборку System.EnterpriseServices.dll. Инструкция lock(<expression>) {// блок кода} является единственным, связанным с синхронизацией, ключевым словом в C#. Оно может применяться, также как в Java, для получения взаимно исключающего доступа к блокировке объекта <ref>. Все попытки получить доступ к <expression> будут блокированы, пока поток выполнения с блокировкой не освободит ее. Обычно используется выражение либо this, либо System.Type, соответствующее Type представленного объекта. Их использование будет защищать переменные экземпляра выражения в то время, как использование System.Type будет защищать статические переменные.

Ключевые слова обработки ошибок: catch, finally, throw, throws, try

Эти модификаторы являются одинаковыми в обоих языках, за исключением инструкции throws, которая отсутствует в C#. Пугающая вещь в отношении инструкции throws из Java состоит в том, что она позволяет потребителям компонента с помощью относительно простого синтаксиса использовать компонент, не зная какие исключения он может порождать. Можно удовлетвориться заверениями, что компилированный код обрабатывает все, имеющие отношение к делу, исключения, так как компилятор будет иначе отказывать и информировать обо всех не перехваченных исключениях. Функциональность такого рода отсутствует в C# в настоящее время. Предоставление метода потребителям сборки, желающем знать, когда порождаются исключения, должно будет привести к хорошей практике документирования или некоторому умелому программированию атрибутов.

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

// OverflowEX.java

public class OverfTowEX {

 publiс static void main(String args []) {

  byte x = 0;

  for (int i = 0; i < 130; i++) {

   x++;

   System.out.println(x);

  }

 }

}

Как известно, byte в Java является 8-битовым типом данных со знаком. Это означает, что диапазон значений byte лежит от -128 до 128. Результатом добавления единицы к любой границе заданного диапазона целого типа будет другая граница диапазона целого типа. Поэтому в этом примере добавление 1 к 127 создаст -128. И если откомпилировать и выполнить эту программу, то последние пять чисел выведенные на консоли будут следующими:

126

127

-128

-127

-126

Это может оказаться весьма существенной проблемой, особенно в связи с тем, что ни предупреждение ни исключение не порождаются, чтобы позволить обработать такое событие (возможно, сохраняя значение в типе с большим диапазоном значений). По умолчанию C# также обрабатывает ситуации переполнения, но язык и компилятор предоставляют инструменты для явной обработки и уведомления программиста в случае переполнения.

□ Программный подход. Чтобы бороться с этим типом молчаливых ошибок, C# вводит концепцию проверяемых и непроверяемых инструкций. Ключевое слово checked используется для управления контекстом проверки переполнения в случае операций и преобразований арифметики целого типа, таких, как представленные выше. Оно может использоваться как оператор или как инструкция. Инструкции checked/unchecked следуют приведенному ниже синтаксису (i). Они предназначены для помещения в скобки ряда инструкций, которые могут создавать переполнение. Синтаксис операции checked/unchecked показан в пункте (ii). Операция checked проверяет переполнение одиночных выражений:

(i) checked {block_of_code}

unchecked { block_of_code}

(ii) checked (expression)

unchecked (expression)

block_of_code содержит код, в котором инструкция checked/unchecked наблюдает за переполнением, a expression представляет выражение, в котором checked/unchecked наблюдает за переполнением в конечном значении. Показанный далее пример иллюстрирует использование checked/unchecked:

// OverflowEX.cs

public class OverflowEX {

 public static void Main(String() args) {

  sbyte x = 0; // помните, что необходимо изменить byte на sbyte

  for (int i = 0; i < 130; i++) {

   checked {

    // можно также использовать checked(x++)

Добавить отзыв
ВСЕ ОТЗЫВЫ О КНИГЕ В ИЗБРАННОЕ

0

Вы можете отметить интересные вам фрагменты текста, которые будут доступны по уникальной ссылке в адресной строке браузера.

Отметить Добавить цитату