Симон Робинсон - C# для профессионалов. Том II
В C# преобразование из строки в число с плавающей точкой выполняется методом Parse(). Однако, так как Parse() является частью класса, ему должно предшествовать имя класса. Класс, на котором необходимо вызвать метод Parse(), будет классом float. До сих пор float интерпретировался просто как эквивалент C# для Single из VB. Но на самом деле он также является классом. В C# все типы данных тоже являются классами, и значит, такие вещи как int, float и string имеют методы и свойства, которые можно вызывать (хотя необходимо отметить, что int и float являются специальными типами класса, известного в C# как структуры. Различие для этого кода не важно, но оно будет объяснено позже.)
Если внимательно посмотреть на приведенный выше код, можно отметить незначительную проблему с аналогией, касающейся модулей класса VB. В методы вызываются определением имени переменной, а не имени модуля класса, но Parse вызван с помощью определения имени класса float, а не имени переменной. Parse() в действительности является специальным типом метода, называемого статическим (static) методом. Статический метод можно вызывать, не создавая экземпляр класса. Следовательно здесь определяется имя класса float, а не имя переменной. static имеет в C# значение, отличное от того, которое он имеет в VB. В C# нет эквивалента статическим переменным VB — в них нет необходимости в объектах C#, так как с этой целью будут использоваться поля C#.
Инструкции If
Мы переходим к основной части обработчика событий — инструкции if. Вспомните, что версия VB выглядит следующим образом:
If (NumberInput < 0) Then
Me.txtSign.Texgt = "Negative"
Me.txtResult.Text = CStr(Sqr(-NumberInput)) & " i"
ElseIf (NumberInput = 0) Then
txtSign.Text = "Zero"
txtResult.Text = "0"
Else
Me.txtSign.Text = "Positive"
Me.txtResult.Text = CStr(Sqr(NumberInput))
EndIf
в то время как версия C# записывается так:
if (NumberInput < 0) {
this.txtSign.Text = "Negative";
this.txtResult.Text = Math.Sqrt(-NumberInput).ToString() + " i";
} else if (NumberInput == 0) {
txtSign.Text = "Zero";
txtResult.Text = "0";
} else {
this.txtSign.Text = "Positive";
this.txtResult.Text = Math.Sqrt(NumberInput).ToString();
}
Фактически наибольшее синтаксическое различие здесь уже было объяснено: каждая часть инструкции в C# должна быть одиночной инструкцией, следовательно, если необходимо условно выполнить более одной инструкции, надо объединить их в одну блочную инструкцию. В C#, если существует только одна инструкция для условного выполнения, не нужно формировать блочную инструкцию. Например, если пропустить задание текста в текстовом поле txtSign в приведенном выше коде, то можно написать:
if (NumberInput < 0) this.txtResult.Text = Math.Sqrt(-NumberInput) + " i";
else if (NumberInput == 0) txtSign.Text = "Zero";
else this.txtResult.Text = Math.Sqrt(NumberInput).ToString();
Существуют и другие различия в синтаксисе, которые необходимо отметить. В C# скобки вокруг условия, которое проверяется в инструкции if, является обязательным. В VB можно написать:
If NumberInput < 0 Then
Попытка выполнить то же самое в C# немедленно приведет к ошибке компиляции. В целом C# значительно более точен в отношении ожидаемого синтаксиса, чем VB. Отметим также, что при проверке равенства нулю NumberInput для сравнения используются два последовательных знака равенства:
else if (NumberInput == 0)
В VB символ = применяется в двух назначениях: для присваивания значений переменным и для сравнения значений. C# формально распознает это как операции двух различных типов и поэтому использует два различных символа: = для присваивания и == для сравнения.
Существует еще одно важное различие, которое надо учитывать, так как оно может легко привести к ошибкам при переходе от VB к C#:
else if состоит в C# из двух слов, а в VB используется одно слово ElseIf
Вычисление квадратного корня: еще один метод класса
В соответствии со сделанным ранее замечанием о том, что все в C# является членом класса, будет неудивительно узнать, что эквивалент в C# функции Sqr из VB, которая вычисляет квадратный корень, также является методом, являющимся членом класса. В данном случае это метод Sqrt(), который представляют статический член другого базового класса .NET с именем System.Math, сокращаемый в коде просто до Math.
Можно также заметить, что в этом примере в условии с введенным числом, точно равным нулю, ключевое слово this в коде C# не определено:
txtSign.Text = "Zero";
txtResult.Text = "0";
и в соответствующем коде VB также не определяется явно Me. В C# по аналогии с VB, не требуется явно определять this (Me), если только по какой-то причине контекст окажется не ясным. Здесь это делается только для иллюстрации.
Строки
При выводе квадратного корня отрицательного числа выполняется небольшая работа со строками:
this.txtResult.Text = Math.Sqrt(-NumberInput).ToString() + " i";
Этот код покалывает, что в C# конкатенация строк делается с помощью символа +, а не &. Можно также заметить, что преобразование из float в String выполняется с помощью вызова метода на объекте float. Метод называется ToString(), и он не является статическим, поэтому вызывается с помощью того же синтаксиса, что и в VB при вызове методов на объектах, способом задания перед именем метода имени переменной, представляющей объект, с точкой. В отношении C# необходимо помнить одну полезную вещь — каждый объект (и следовательно, каждая переменная) реализует метод ToString().
Дополнительный код в C#
Мы завершили сравнение процедур обработки событий в C# и VB. В процессе обсуждения мы много узнали о синтаксических различиях между этими языками. Фактически была показана большая часть базового синтаксиса C#. Мы также впервые столкнулись с тем фактом, что все в C# является классом. Однако, если загрузить код нашего примера с web-сайта издательства Wrox, и просмотреть его, то почти наверняка можно будет заметить, что мы тщательно избегали какого-либо обсуждения наиболее очевидного различия между двумя примерами: в примере на C# в действительности код намного длиннее и включает не только обработчик событий. Для версии VB примера SquareRoot код обработчика событий, который здесь представлен, представляет весь исходный код этого проекта. Напротив, в версии C# этот обработчик событий является только одним методом в огромном файле исходного кода.
Причина, по которой код в проекте C# такой большой, связана с тем, что Visual Basic IDE большая часть того, что делается в программе, исходит от программиста. В Visual Basic требовалось написать только обработчик событий, но фактически выполняется значительно больше: запускается пример, выводится форма на экране, посылается информация Windows, зависящая от того, что желательно делать с событиями, и по окончании пример завершается. В Visual Basic программист не имеет доступа к коду, который делает все. C#, напротив, использует совершенно другую философию, и оставляет весь этот код открытым. Это может сделать внешний вид исходного кода более сложным. Но имеется одно преимущество: если код доступен, то его можно редактировать и это обеспечивает значительно большую гибкость в решении того, как должно себя вести приложение.
Фактически Visual Basic настолько успешно скрывает почти все, что происходит в программе, что очень легко стать профессиональным программистом и создавать достаточно сложные приложения, не имея на самом деле никакого представления о полной структуре компьютерной программы. В следующем разделе будет рассмотрено, что же происходит в любой такой программе, и таким образом мы будем готовы взглянуть на весь дополнительный код, который содержится в версии C# программы SquareRoot.
Что происходит при выполнении программы
Любая программа содержит точную последовательность выполнения. Когда приложение запускается, будет существовать определенное место в исполнимом коде, с которого, как знает компьютер, он должен начать выполнение кода, другими словами, инструкция, которая выполняется первой. Затем будет идти следующая инструкция, и следующая, и следующая и так далее. Некоторые из этих команд прикажут компьютеру перепрыгнуть к другой инструкции, возможно в зависимости от значений, которые содержатся в некоторых переменных. Очень часто компьютер будет перепрыгивать назад и выполнять ту же самую инструкцию снова. Однако всегда существует эта непрерывная последовательность выполнения следующей инструкции, пока компьютер не встретит команду, которая прикажет ему прекратить выполнение кода. Такая линейная последовательность справедлива для любой программы. Некоторые программы могут быть мультипоточными, и в этом случае существует несколько последовательностей выполнения (потоков выполнения), но каждый поток по-прежнему будет следовать от начальной инструкции до остановки программы.