C# для профессионалов. Том II - Симон Робинсон
Шрифт:
Интервал:
Закладка:
(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++)
x++;
Console.WriteLine(x);
}
}
}
}
□ Подход с ключом компилятора. Для контроля переполнения во всем приложении может использоваться настройка компилятора /checked+. Чтобы проиллюстрировать это, удалим инструкцию checked из приведенного выше примера и попытаемся компилировать его, используя флаг /checked+. С его помощью можно включать и выключать проверку арифметического переполнения, изменяя состояние конфигурационных свойств на странице свойств проекта. Задание значения как true будет включать проверку переполнения.
При включенной проверке переполнения можно обсудить использование инструкции unchecked. По сути она предоставляет функциональность для произвольного исключения проверки выражений или блоков инструкций в то время, когда включена проверка во всем приложении. В примере ниже предыдущая инструкция заменяется инструкцией unchecked. Компиляция и выполнение этого кода будет создавать вывод, аналогичный выводу OverflowEX.java.
// OverflowEX.сs.
public class OverflowEX {
public static void Main(String[] args) {
sbyte X = 0;
for (int i = 0; i < 130; i++) {
unchecked { // можно также использовать unchecked(x++)
x++;
Console.WriteLine(x);
}
}
}
}
Входные и выходные данные
Возможность собрать входные данные из командной строки и вывести данные в командной строке является интегральной частью функциональности ввода/вывода в Java. Обычно в Java необходимо создать экземпляр объекта java.io.BufferedReader, используя поле System.in, чтобы извлечь ввод из командной строки. Ниже представлен простой класс Java — JavaEcho, который получает ввод с консоли и выводит его обратно, чтобы проиллюстрировать использование пакета Java.io для сбора и форматирования ввода и вывода:
// JavaEcho.java
import java.io.*;
public class JavaEcho {
public static void main(String[] args) throws IOException {
BufferedReader stdin = new BufferedReader(new InputSreamReader(System.in));
String userInput = stdin.readLine();
System.out.println("You said: " + userInput);
}
}
Класс System.Console предоставляет методы в C#, которые дают аналогичную функциональность для чтения и записи из и в командную строку, Нет необходимости в каких-либо дополнительных объектах, класс Console предоставляет методы, которые могут читать целые строки, читать символ за символом и даже показывать описанный выше поток, из которого выполняется чтение. Важно отметить, что эту функциональность дает System.Console без создания экземпляра объекта Console. Фактически можно обнаружить, что невозможно создать экземпляр объекта Console. Члены класса Console кратко описаны в таблицах ниже:
Открытые статические свойства (общие) Описание Error Получает стандартный выходной поток ошибок системы In Получает стандартный входной поток ошибок системы Out Получает стандартный поток вывода системы Открытые статические методы (общие) Описание OpenStandardError Перезагруженный. Возвращает стандартный поток ошибок. OpenStandardInput Перезагруженный. Возвращает стандартный поток ввода. OpenStandardOutput Перезагруженный. Возвращает стандартный поток вывода. Read Читает следующий символ из стандартного потока ввода. ReadLine Читает следующую строку символов из Console.In, который по умолчанию задается как стандартный поток ввода системы. SetError Перенаправляет свойство Error для использования указанного потока TextWriter. SetIn Перенаправляет свойство In для использования указанного потока TextReader. SetOut Перенаправляет свойство Out для использования указанного потока TextWriter. Write Перезагруженный. Записывает указанную информацию в Console.Out. WriteLine Перезагруженный. Записывает информацию, за которой следует конец строки в Console.Out.Как можно видеть, все члены Console являются статическими. static является примером модификатора C#. Он обладает тем же значением, что и его аналог в Java, т.е. делает указанную переменную или метод принадлежащим всему классу, а не одному какому-то экземпляру класса. Мы обсудим модификаторы более подробно позже в этом приложении.
С помощью мощных методов из класса Console можно записать эквивалент класса JavaEcho на C# следующим образом:
class CSEchoer {
static void Main(string[] args) {
string userInput = System.Console.ReadLine();
System.Console.WriteLine("You said : " + userInput);
}
}
Приведенный выше код значительно короче и легче, чем его аналог на Java. Статический метод Console.WriteLine предоставляет одну полезную вещь, а именно, возможность использовать форматированные строки. Гибкость форматированных строк может быть проиллюстрирована написанием простой игры, где ввод пользователя применяется для создания рассказа. Код EchoGame представлен ниже:
class EchoGame {
static void Main(string[] args) {
System.Console.WriteLine("Once upon a time in a far away" + "?");
string userInput1 = System.Console.ReadLine();
System.Console.WriteLine("a young prince ?");
string userInput2 = System.Console.ReadLine();
System.Console.WriteLine("One day while?");
string userInput3 ? System.Console.ReadLine();
System.Console.WriteLine("He came across a ?");
string userInput4 = System.ConsoleReadLine();
System.Console.WriteLine("The prince ?");
String userInput5 = System.Console.ReadLine();
System.Console.WriteLine("Once upon a time in a far away"
+ " {0}, a young prince {1}. n One day"
+ "while {2}, He came across a (3). n The "
+ "prince {4} ! ", userInput1, userInput2,
userInput3, userInput4, userInput5);
}
}
Точки вставки заменяются предоставленными аргументами, начиная с индекса {0}, который соответствует самой левой переменной (в данном случае userInput1). Можно подставлять не только строковые переменные, и не обязательно использовать только переменные или переменные одного типа. Любой тип данных, который может вывести метод WriteLine, допустим в качестве аргумента, включая строковые литералы или реальные значения. Не существует также ограничений на число точек вставки, которые могут добавляться к строке, пока их не больше общего числа аргументов. Отметим, что исключение точек вставки из строки приведет к тому, что переменные не будут выводиться. Необходимо, однако, иметь аргумент для каждой определенной точки вставки, индекс которой в списке аргументов соответствует индексу точки вставки. В следующем листинге, например, удаление {1} допустимо, пока имеется три аргумента. В этом случае {0} соответствует strA и {2} соответствует strC:
Console.WriteLine("hello {0} {1} {2}", strA, strB, strC);
Компиляция
При описании некоторых различий между JRE Java и CLR C# кратко упоминались некоторые детали того, как написанный на соответствующем языке код компилируется и выполняется. Хотя код обоих языков компилируется в некоторую промежуточную форму, байт-код версии Java никогда не компилируется повторно в собственные инструкции машины (если только не используется компилятор в собственный код). Вместо этого байт-код требует для выполнения среду времени выполнения, и в частности, виртуальную машину. Имя компилированного файла связано с именем файла, в котором находится исходный код, который в свою очередь связан с именем открытого класса в этом файле. В случае определения нескольких классов в одном файле каждое определение класса будет создавать файл класса, который соответствует имени определенного класса. Например, возьмем исходный файл Test.java со следующим кодом: