Язык программирования и среда разработки. Цели курса
Консольный проект
Наша цель состоит в том, чтобы построить интерфейс, обеспечивающий конечному пользователю доступ к тем сервисам, которые предоставляет построенная DLL. Начнем с построения простейшего интерфейса, позволяющего пользователю с консоли вводить исходную информацию - в нашем случае аргумент x. С исходными данными пользователь может провести вычисления, вызвав сервисы, предоставляемые DLL, а затем полученные результаты вывести на консоль - экран дисплея. Для организации подобного интерфейса и служит тип проекта - Console Application.
Чтобы создать новый проект, находясь в среде разработки, вовсе не обязательно начинать со стартовой страницы. Достаточно выбрать пункт меню File|New|Project, приводящий на страницу создания нового проекта, показанную на рис. 1.5. В этом окне, как описано ранее, зададим тип строящегося проекта, дадим ему имя - ConsoleToMathTools, укажем, что проект добавляется к существующему Решению Ch1. В результате в уже существующее Решение добавится еще один проект, что отображено на рис. 1.7.
Как показано на рис. 1.7, в консольном проекте автоматически создается класс с именем Program, содержащий единственный статический метод - процедуру Main. Если скомпилировать этот проект и запустить его на выполнение, то начнет выполняться код этой процедуры, пока отсутствующий - его предстоит нам создать.
Начало начал - точка "большого взрыва"
Основной операцией, инициирующей вычисления в объектно-ориентированных приложениях, является вызов метода F некоторого класса, имеющий вид:
x.F(arg1, arg2, …, argN)
В этом вызове x - это некоторый существующий объект, называемый целью вызова. Возможны три ситуации:
- x - имя класса. Объектом в этом случае является статический объект, который всегда создается в момент трансляции кода класса. Метод F должен быть статическим методом класса, объявленным с атрибутом static, как это имеет место для точки вызова - процедуры Main ;
- x - имя объекта или объектное выражение. В этом случае F может быть обычным, не статическим методом. Иногда такой метод называют экземплярным, подчеркивая тот факт, что метод вызывается экземпляром класса - некоторым объектом;
- x - не указывается при вызове. В отличие от двух первых случаев такой вызов называется неквалифицированным. Заметьте, неквалифицированный вызов вовсе не означает, что цель вызова отсутствует, - она просто задана по умолчанию. Целью является текущий объект, имеющий зарезервированное имя this. Применяя это имя, любой неквалифицированный вызов можно превратить в квалифицированный вызов. Иногда без этого имени просто не обойтись.
Но как появляются объекты? Как они становятся текущими? Как реализуется самый первый вызов метода, другими словами, кто и где вызывает точку входа - метод Main? С чего все начинается?
Когда Решение запускается на выполнение, в него должна входить сборка, отмеченная как стартовый проект, содержащая класс с точкой входа - статическим методом (процедурой) Main. Некоторый объект исполнительной среды CLR и вызывает этот метод, так что первоначальный вызов метода осуществляется извне приложения. Это и есть точка "большого взрыва" - начало зарождения мира объектов и объектных вычислений. Извне создается и первый объект, задающий статический модуль с методом Main. Этот объект и становится текущим.
Дальнейший сценарий зависит от содержимого точки входа. Как правило, в процессе работы метода Main создаются один или несколько объектов других классов, они и вызывают методы и/или обработчики событий, происходящих с созданными объектами. В этих методах и обработчиках событий могут создаваться новые объекты, вызываться новые методы и новые обработчики. Так, начиная с одной точки, разворачивается целый мир объектов приложения.
Связывание с DLL
Первым делом свяжем два построенных проекта, для чего в консольный проект добавим ссылку на проект с DLL MathTools. В окне Solution Explorer подведем указатель мыши к имени консольного проекта и из контекстного меню, появляющегося при щелчке правой кнопки, выберем пункт меню "Add Reference". В открывшемся окне добавления ссылок выберем вкладку "Projects". Поскольку проект MathTools включен в Решение, то он автоматически появится в открывшемся окне. Если ссылку нужно установить на проект, не включенный в Решение, то в окне добавления ссылок нужно задать путь к проекту. Нам проще, путь указывать не нужно, достаточно щелкнуть по появившемуся в окне имени MathTools. Ссылка на DLL появится в папке "References" консольного проекта. Теперь проекты связаны и из консольного проекта доступны сервисы, предоставляемые DLL.
Организация консольного интерфейса
Задача кода, который мы встроим непосредственно в уже созданную процедуру Main, достаточно понятна. Необходимо объявить и создать объекты, представляющие входные данные, организовать диалог с пользователем для ввода этих данных, обратиться к сервисам DLL для получения результата и результаты вывести на консоль. Приведу вначале код консольного проекта с построенным методом Main, а затем его прокомментирую. Вот этот код:
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ConsoleToMathTools { class Program { /// <summary> /// Точка входа в консольный проект /// организация интерфейса к DLL MathTools /// </summary> /// <param name="args"></param> static void Main(string[] args) { //Входные данные double x = 0; const string INVITE = "Введите вещественное число x" + "- аргумент функции Sin(x)"; const string CONTINUE = "Продолжим? (Yes/No)"; string answer = "yes"; do { //Организация ввода данных Console.WriteLine(INVITE); string temp = Console.ReadLine(); x = Convert.ToDouble(temp); //Вычисления и вывод результата double res = 0; res = Math.Sin(x); Console.WriteLine("Math.Sin(x) = " + res.ToString()); res = MathTools.MyMath.Sin(x); Console.WriteLine("MathTools.MyMath.Sin(x) = " + res.ToString()); res = MathTools.MyMath.SinOld(x); Console.WriteLine("MathTools.MyMath.SinOld(x) = " + res.ToString()); //диалог с пользователем Console.WriteLine(CONTINUE); answer = Console.ReadLine(); } while (answer == "yes"); } } }
Дадим краткие комментарии к этому коду.
Входные данные устроены просто - задается лишь одна переменная x типа double. Помните, что в языке C# все переменные являются объектами.
Вводу значения x предшествует, как и положено для хорошего стиля программирования, приглашение к вводу. Для ввода и вывода значений используются статические методы ReadLine и WriteLine класса Console, входящего в библиотеку FCL и предоставляющего свои сервисы пользователям консольных приложений. Для преобразования введенных данных, представляющих собой строки текста, к нужному типу (в нашем случае к типу double) используются статические методы класса Convert, сервисы которого позволяют проводить различные преобразования между типами данных.
Значение функции вычисляется тремя разными методами - методом стандартного класса Math и двумя методами класса MyMath, входящего в состав библиотеки MathTools.
Следуя правилу стиля "Имена - константам", в коде метода используются именованные константы.
Применяется стандартный прием зацикливания тела метода Main, позволяющий пользователю самому решать, когда прервать выполнение метода.
На рис. 1.8 показаны результаты работы консольного проекта.
Анализируя эти результаты, можно видеть, что все три метода на всех исследуемых аргументах дают одинаковые результаты, совпадающие с точностью до 9 цифр после запятой. Точность методов в классе MyMath обеспечивается константой EPS этого класса. Достигнутая точность вполне достаточна для большинства практических задач. Остается понять, насколько написанные нами методы проигрывают методу стандартного класса по времени. Это исследование оставим для следующего проекта - Windows-проекта, обеспечивающего интерфейс, который дает пользователю больше возможностей.