C# для профессионалов. Том II - Симон Робинсон
Шрифт:
Интервал:
Закладка:
Конечно, эта последовательность не та, которую можно видеть при написании исполнимой программы VB. В VB6 по сути пишется набор обработчиков событий — набор подпрограмм, каждая из которых вызывается, когда пользователь что-то сделает. Не существует единственного начала программы, хотя обработчик события Form_Load близко подходит к этому по своей концепции. Даже в этом случае Form_Load является на самом деле только еще одним обработчиком для события, которое возникает, когда загружается форма, и значит, оно будет первым выполняющимся событием. Аналогично, если вместо исполнимого кода пишется элемент управления или объект класса, то нет начальной точки. Просто задается класс и к нему добавляется множество методов и свойств. Каждый метод или свойство будет выполняться, если или когда код клиента его вызывает.
В действительности приведенный выше абзац не совсем справедлив. В VB существует процедура Sub Main(), которая действует как точка входа программы, но она не часто используется. Поскольку здесь сравнивается типичная программа C# с типичной программой VB, то точка зрения, констатирующая, что программы VB в действительности показывают код только для событие в общем оказывается правильной.
Чтобы увидеть, как можно связать две идеи программирования, давайте выясним, что реально происходит, когда выполняется любое приложение Visual Basic или любое приложение GUI Windows, не важно на каком языке оно написано. Это более ограниченное рассмотрение, чем в случае приложении, которые упоминались перед этим, так как теперь мы сосредоточимся только на приложениях Windows API (другими словами, нет консолей, служб и т.д.).
Как обычно, выполнение начинается в некоторой вполне определенной точке. Команды будут вовлекать в работу некоторые окна и элементы управления, а также вывод этих элементов управления на экран. В этом месте программа делает затем что-то, что называют входом в цикл сообщений. На самом деле программа засыпает и приказывает Windows разбудить себя, когда произойдет что-то интересное, о чем ей необходимо знать. Эти "интересные" вещи являются событиями, для которых необходимо написать обработчики событий, а также существует достаточно много событий, для которых не требуется писать свои собственные обработчики событий, так как если обработчик для определенного события написан не будет, то VB IDE спокойно представляет готовый по умолчанию. Хорошим примером этого являются обработчики, которые имеют дело с изменением размера формы. Исходный код для него никогда не показывается в VB, но приложение VB может правильно отреагировать, когда пользователь попытается изменить размер, поскольку VB IDE незаметно добавляет в проект обработчики событий, которые правильно управляют этой ситуацией.
Когда происходит событие, Windows пробуждает приложение и вызывает соответствующим обработчик событий, именно в этот момент может начать выполняться код программиста. Когда процедура обработчика событий заканчивается, приложение снова переведет себя в спящий режим, приказывая Windows разбудить себя, когда произойдет другое интересное событие. Наконец, предполагая, что ничего не произошло разрушительного и неверного, в некоторый момент Windows разбудит приложение и проинформирует его, что необходимо прекратить работу. В этот момент приложение предпримет все необходимые действия — например, выведет окно сообщения, спрашивающего у пользователя, не хочет ли он сохранить файл и затем спокойно завершится. Снова большая часть кода, который это делает, добавляется в проект неявно VB IDE, и программист никогда его не видит.
Поток выполнения в типичном приложении GUI Windows выглядит примерно следующим образом:
На этой диаграмме рамка с пунктирной границей указывает ту часть исполнимого кода, к которой VB IDE предоставляет программисту доступ и для которого можно писать исходный код,— это несколько обработчиков событий. Остальная часть кода недоступна для программиста, хотя его можно в некоторой степени определить, выбирая тип приложения при запросе к VB на создание проекта. Для нового проекта в VB появляется диалоговое окно, запрашивающее тип приложения, которое требуется создать,— стандартный EXE, ActiveX EXE, ActiveX DLL и т.д. После выбора VB IDE использует его для генерации всего необходимого кода в той части программы, которая находится вне пунктирной рамки на приведенной выше диаграмме. Диаграмма показывает ситуацию, когда выбрано создание проекта стандартного EXE, отличающегося от других типов проектов (например, ActiveX DLL вообще не имеет цикла сообщений, но вместо этого зависит от клиентов в отношении вызова методов), и при этом дается примерное представление о том, что происходит.
Ранее было сказано, что в C# программист получает доступ ко всему коду, теперь необходимо это уточнить: все мельчайшие подробности относительно того, что происходит в цикле сообщений, надежно скрыты внутри различных DLL, которые написала компания Microsoft, но можно видеть методы верхнего уровня, вызывающие различные элементы обработки. Допустим, имеются доступы к коду, который начинает выполнение всей программы, к вызову библиотечного метода, который заставляет программу войти в цикл сообщений и переводит ее в спящее состояние и т.д. Имеется также доступ к исходному коду, создающему экземпляры всех различных элементов управления, которые помещаются на форме, делая эти экземпляры видимыми и определяя их начальные положения, размеры и все остальное. Необходимо отметить еще и тот момент, что не требуется писать никакой подобный код самостоятельно. При использовании Visual Studio.NET для создания проекта C# по-прежнему появляется диалоговое окно, спрашивающее, какой тип проекта необходимо создать, и Visual Studio.NET будет по-прежнему готовить весь базовый код. Различие состоит в том, что Visual Studio.NET записывает этот базовый код, как исходный на C#, который затем можно непосредственно редактировать.
Все это приводит к тому, что исходный код получается более длинным и более сложным. Однако огромное его преимущество заключается в том, что он обеспечивает значительно большую гибкость в том, что делает программа и как она себя ведет. А значит, можно написать намного больше типов проектов в C#. В то время как в Visual Basic возможно написание только различных видов форм и компонентов COM, в C# вы в праве написать любую из различных типов программ, которые выполняются под Windows. Это включает, например, консольные приложения (командной строки) и страницы ASP.NET (наследник ASP), что нельзя написать в VB6 (можно использовать VBScript для страниц ASP). В этом приложении, однако, мы сосредоточимся на классических приложениях GUI для Windows.
Код C# для оставшейся части программы
В этом разделе будет рассмотрена оставшаяся часть кода для примера SquareSample, в результате чего мы узнаем немного больше о классах в C#.
Пример SquareRoot на C# был создан в Visual Studio.NET, а пример на VB — в IDE VB6. Однако представленный здесь код является не совсем тем, который сгенерировала Visual Studio.NET. Помимо добавления обработчика событий, сделаны и другие изменения в коде, чтобы лучше проиллюстрировать принципы программирования в C#. Но несмотря ни на что, он все-таки даст хорошее представление о той работе, которую делает Visual Studio.NET, когда создает проект.
Весь текст исходного кода достаточно длинный. Он представлен здесь для полноты, но лучше сразу перейти к последующим объяснениям и обращаться к исходному коду по мере необходимости.
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
namespace Wrox.ProfessionalCSharp.AppendixC.SquareRootSample {
/// <summary>
/// Form, которая формирует основное окно приложения:
/// </summary>
public class SquareRootForm : System.Windows.Forms.Form {
private System.Windows.Forms.TextBox txtNumber;
private System.Windows.Forms.TextBox txtSign;
private System.Windows.Forms.TextBox txtResult;
private System.Windows.Forms.Button cmdShowResults;
private System.Windows.Forms.Label label1;
private System.Windows.Forms.Label label2;
private System.Windows Forms.Label label3;
private System.Windows.Forms.Label label4;
/// <summary>
/// Необходимые для designer переменные.
/// </summary>
private System.ComponentModel.Container components;
public SquareRootForm() {
InitializeComponent();
}
public override void Dispose() {
base.Dispose();
if(components != null) components.Dispose();
}
#region Windows Form Designer generated code
/// <summary>
/// Требуемый для поддержки Designer метод - не изменять
/// содержимое этого метода с помощью редактора кода.
/// </summary>