Большинство видов инструкций в Java и C# являются общими и заимствованы из языка C. В обоих языках есть понятие блока — набора инструкций, заключенного в фигурные скобки.
Инициализировать переменную можно каким-то значением ее типа. Использование неинициализированных переменных во многих случаях определяется компилятором и считается ошибкой (но не всегда). Однако даже при отсутствии инициализации переменной, ей все равно будет присвоено значение по умолчанию для данного типа.
Массивы могут быть инициализированы с помощью специальных выражений, перечисляющих значения элементов массива, например
int[][] array = new int[][]{{0, 1}, {2, 3, 4}}; Ag
if(expression) statement Ag
или
if(expression) statement else statement1 Ag
где expression — выражение логического типа (или приводящегося к логическому), а statement и statement1 — инструкции.
switch(expression) { … } Ag
Внутри ее блока различные варианты действий для различных значений выражения expression описываются с помощью списков инструкций, помеченных либо меткой case с возможным значением выражения, либо меткой default. Группа инструкций, помеченная default, выполняется, если значение выражения выбора не совпало ни с одним из значений, указанных в метках case.
Один набор инструкций может быть помечен несколькими метками. Наборы инструкций могут отделяться друг от друга инструкциями break;
Тип expression может быть целочисленным или приводящимся к нему, либо перечислимым типом. В C# допускается использование для выбора выражений типа string.
Значения, которые используются в метках case, должны быть константными выражениями.
В Java группа инструкций для одного значения может оканчиваться инструкцией break, а может и не оканчиваться. Во втором случае после ее выполнения управление переходит на следующую группу инструкций. | В C# группа инструкций для одного значения (включая и группу, помеченную default) всегда должна оканчиваться либо break, либо goto default, либо goto case value с каким-то из значений, указанных в рамках той же инструкции выбора. |
public class A { public static void main(String[] args) { if(args.length > 0) { int n = Integer.parseInt(args[0]); switch(n) { case 0: System.out.println("n = 0"); case 1: System.out.println ("n = 0 or n = 1"); break; case 2:case 3: System.out.println ("n = 2 or n = 3"); break; default: System.out.println ("n is out of [0..3]"); } } else System.out.println("No arguments"); } } | using System; public class A { public static void Main(string[] args) { if(args.Length > 0) { int n = Int32.Parse(args[0]); switch(n) { case 0: Console.WriteLine("n = 0"); goto case 1; case 1: Console.WriteLine ("n = 0 or n = 1"); break; case 2:case 3: Console.WriteLine ("n = 2 or n = 3"); break; default: Console.WriteLine ("n is out of [0..3]"); break; } } else Console.WriteLine("No arguments"); } } |
В Java синтаксис цикла перебора элементов коллекции такой: for ( finalopt type id : expression ) statement При этом выражение expression должно иметь тип java.lang.Iterable или тип массива. В первом случае такой цикл эквивалентен следующему (T далее обозначает тип результат метода iterator() у expression, v — нигде не используемое имя). for(T v = expression.iterator(); v.hasNext(); ) { finalopt type id = v.next(); statement } Во втором случае, когда expression — массив типа T[], эта конструкция эквивалентна следующей (a, i — нигде не используемые имена) T[] a = expression; for(int i = 0; i < a.length; i++) { finalopt type id = v.next(); statement } | В C# синтаксис цикла перебора элементов коллекции такой: foreach ( type id in expression ) statement Выражение expression должно быть массивом, или иметь тип System.Collections.IEnumerable или System.Collections.Generic.IEnumerable <T>, или же его тип должен иметь метод GetEnumerator(), результат которого, в свою очередь, должен иметь свойство Current и метод MoveNext(). Тип результата метода GetEnumerator() во всех случаях, кроме массива, называется типом итератора (enumerator type). Тип свойства Current, которое имеется у типа итератора, должен совпадать с type. Пусть тип итератора E, а e — неиспользуемое имя. Тогда приведенная конструкция, с точностью до некоторых деталей, эквивалентна следующей. E e = expression.GetEnumerator(); while(e.MoveNext()) { type id = (type)e.Current; statement } Опущенные детали касаются освобождения ресурсов, используемых итератором (см. далее описание инструкции using). |
Пример использования перебора элементов коллекции: | Пример использования перебора элементов коллекции: |
public class A { public static void main(String[] args) { int i = 1; for(String s : args) System.out.println((i++) + "-th argument is " + s); } } | using System; public class A { public static void Main(string[] args) { int i = 1; foreach (string s in args) Console.WriteLine((i++) + "-th argument is " + s); } } |
В Java инструкция break используется для прерывания выполнения не только циклов, но и обычных блоков (наборов инструкций, заключенных в фигурные скобки). Более того, после break (или continue) может стоять метка. Тогда прерывается выполнение того блока/цикла (или же начинается новая итерация того цикла), который помечен этой меткой. Этот блок (или цикл) должен содержать такую инструкцию внутри себя. |
| public class A { public static void main(String[] args) { try { if(args.length > 0) System.out.println ("Some arguments are specified"); else throw new IllegalArgumentException ("No arguments specified"); } catch(RuntimeException e) { System.out.println ("Exception caught"); System.out.println ("Exception type is " + e.getClass().getName()); System.out.println ("Exception message is \"" + e.getMessage() + "\""); } finally { System.out.println ("Performing finalization"); } } } | using System; public class A { public static void Main(string[] args) { try { if(args.Length > 0) Console.WriteLine ("Some arguments are specified"); else throw new ArgumentException ("No arguments specified"); } catch(Exception e) { Console.WriteLine ("Exception caught"); Console.WriteLine ("Exception type is " + e.GetType().FullName); Console.WriteLine ("Exception message is \"" + e.Message + "\""); } finally { Console.WriteLine ("Performing finalization"); } } } |
В Java, начиная с версии 1.4, появилась инструкция assert, предназначенная для выдачи отладочных сообщений. Эта инструкция имеет один из двух видов: assert expression ; assert expression : expression_s ; Выражение expression должно иметь логический тип, а выражение expression_s — произвольный. Проверка таких утверждений может быть выключена. Тогда эта инструкция ничего не делает, и значения входящих в нее выражений не вычисляются. Если проверка утверждений включена, то вычисляется значение expression. Если оно равно true, управление переходит дальше, иначе в обоих случаях выбрасывается исключение java.lang.AssertionError. Во втором случае еще до выброса исключения вычисляется значение выражения expression_s, оно преобразуется в строку и записывается в качестве сообщения в создаваемое исключение. | |
В C# имеется возможность использовать инструкцию goto. Эта инструкция передает управления на инструкцию, помеченную меткой, которая следует за goto. Как мы уже видели, помимо обычных меток, в goto могут использоваться метки case вместе со значениями и метка default. В этих случаях инструкция goto должна находиться внутри блока switch, в котором имеются эти метки. При выходе с помощью goto из блока try или блока catch, у которых имеется соответствующий блок finally, сначала выполняется содержимое этого блока finally. | |
Ключевые слова checked и unchecked в C# могут помечать блок, определяя тем самым контекст вычислений в рамках этого блока (см. раздел о целочисленных типах). | |
Инструкция using может быть использована в C#, чтобы выполнить действия, требующие захвата каких-либо ресурсов, без необходимости заботиться потом об их освобождении. Эта инструкция имеет вид: using ( expression ) statement или using ( declaration ) statement где declaration — это декларация одной или нескольких переменных. Первый вид этой инструкции сводится ко второму — если тип используемого выражения T, и имя v нигде не используется, то он эквивалентен using ( T v = expression ) statement Эта конструкция, в свою очередь, эквивалентна следующей. { T v = expression; try { statement } finally { disposal } } Здесь disposal представляет вызов метода Dispose(), который должен быть у типа T, с возможной предварительной проверкой того, что переменная v не равна null, и приведением ее к типу System.IDisposable, если T является его подтипом. | |
В версии 2.0 в C# введены две инструкции yield, предназначенные для более удобного построения итераторов. Блок, содержащий инструкцию yield, называется итерационным (iterator block) и может быть телом метода, оператора или метода доступа к свойству и не должен быть блоком finally, catch или блоком try, у которого есть соответствующие catch-блоки. Этот блок порождает последовательность значений одного типа. Сам метод или оператор должен возвращать объект одного из четырех типов: System.Collections.IEnumerable, System.Collections.IEnumerator, System.Collections.Generic.IEnumerable <T>, System.Collections.Generic.IEnumerator <T>. В первых двух случаях порождаются объекты типа object, во вторых двух — значения типа T. Для возвращения одного из этой последовательности значений используется инструкция yield return expression; Выражение в ней должно иметь соответствующий тип, object или T. Для указания на то, что порождаемая итерационным блоком последовательность значений завершилась, используется инструкция yield break; Пример реализации итератора коллекции с использованием yield приведен ниже. | |
| using System; public class MyArrayList<T> { T[] items = new T[10]; int size = 0; public int Count { get { return size; } } public T this[int i] { get { if(i < 0 || i >= size) throw new IndexOutOfRangeException(); else return items[i]; } set { if(i < 0 || i > size) throw new IndexOutOfRangeException(); else if (i == size) { T[] newItems = new T[size + 10]; Array.Copy (items, newItems, size++); } items[i] = value; } } public IEnumerator<T> GetEnumerator () { for(int i = 0; i < size; i++) yield return items[i]; } } public class A { public static void Main() { MyArrayList<string> l = new MyArrayList<string>(); l[0] = "First"; l[1] = "Second"; l[2] = "Third"; foreach (string s in l) Console.WriteLine(s); } } |