Методические рекомендации по выполнению практических работ по междисциплинарному курсу
Скачать 2.6 Mb.
|
partial class Form1 : Form { Graphics gr; //объявляем объект - графику, на которой будем рисовать Pen p; //объявляем объект - карандаш, которым будем рисовать контур SolidBrush fon; //объявляем объект - заливки, для заливки соответственно фона SolidBrush fig; //и внутренности рисуемой фигуры int rad; // переменная для хранения радиуса рисуемых кругов Random rand; // объект, для получения случайных чисел public Form1() { InitializeComponent(); } //опишем функцию, которая будет рисовать круг по координатам его центра void DrawCircle(int x, int y) { int xc, yc; xc = x - rad; yc = y - rad; gr.FillEllipse(fig, xc, yc, rad, rad); gr.DrawEllipse(p, xc, yc, rad, rad); } // для перехода к данной функции сделайте двойной щелчок по кнопке (Button) // добавленной на форму. См. на фото, после кода private void button1_Click(object sender, EventArgs e) { gr = pictureBox1.CreateGraphics(); //инициализируем объект типа графики // привязав к PictureBox p = new Pen(Color.Lime); // задали цвет для карандаша fon = new SolidBrush(Color.Black); // и для заливки fig = new SolidBrush(Color.Purple); rad = 40; //задали радиус для круга rand = new Random(); //инициализируем объект для рандомных числе gr.FillRectangle(fon, 0, 0, pictureBox1.Width, pictureBox1.Height); // закрасим черным // нашу область рисования // вызываем написанную нами функцию, для прорисовки круга // случайным образом выбрав перед этим координаты центра int x, y; for (int i = 0; i < 15; i++) { x = rand.Next(pictureBox1.Width); y = rand.Next(pictureBox1.Height); DrawCircle(x, y); } timer1.Enabled = true; //включим в работу наш таймер, // то есть теперь будет происходить событие Tick и его будет обрабатывать функция On_Tick (по умолчанию) } // для получения данной функции перейдите к конструктору формы // и сделайте двойной щелчок по таймеру, добавленному на форму. См. на фото после кода private void timer1_Tick(object sender, EventArgs e) { //сначала будем очищать область рисования цветом фона gr.FillRectangle(fon, 0, 0, pictureBox1.Width, pictureBox1.Height); // затем опять случайным образом выбираем координаты центров кругов // и рисуем их при помощи описанной нами функции int x, y; for (int i = 0; i < 15; i++) { x = rand.Next(pictureBox1.Width); y = rand.Next(pictureBox1.Height); DrawCircle(x, y); } } } } После этого, можно запустить программу и после нажатия на кнопку увидите простую анимацию – случайное перемещение кругов по черному фону, как показано ниже: Для того, чтобы анимация соответствовала требованиям иногда необходимо менять так называемый тик таймера, т.е. промежуток выполнения очередного шага анимации. Это выполняется в Инспекторе объектов. Нужно выбрать элемент Timer, нажать на кнопку Свойства и там выбрать и изменить параметр Interval (выражается в миллисекундах) В данном примере Interval равен 150 мс. Практическая работа №24 Оптимизация и рефакторинг кода Рефакторинг- своего рода перепроектирования кода программы, уменьшив ее в объеме но не изменив ее функциональности, порой после рефакторинга код программы может сократиться в десятки раз. И так рассмотрим код метода. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 static bool ShouldFire(bool enemyInFront, string enemyName, int robotHealth) { bool shouldFire = true; if (enemyInFront == true) { if (enemyName == "boss") { if (robotHealth < 50) shouldFire = false; if (robotHealth > 100) shouldFire = true; } } else { return false; } return shouldFire; } Посмотрев на код выше, сразу бросается количество ветвлений условных операторов. И относительно не большая функциональность метода, занимает слишком много строк кода. Попробуйте самостоятельно уменьшить ее размер и если ли не получиться подстмотрите код ниже. Функциональность метода нельзя нарушать, лишь сократить ее в объеме. В первую очередь для меня бросается локальная переменная shouldFire которая тут вообще не нужна. А весь остальной код можно сгруппировать в return. И так смотрите что у меня получилось: 1 2 3 4 static bool ShouldFire2(bool enemyInFront, string enemyName, int robotHealth) { return enemyInFront? ((enemyName=="boss")&& robotHealth<50?false:true):false; } Метод настолько уменьшился что поместился в одну строку, а функциональность его осталось не изменой. Рефакторинг программы следует проводить только тогда, кода ваш код рабочий, не имеет ошибок. Только после этого надо думать над тем как его уменьшить. Но сильно уменьшать его тоже не стоит, так как сокращение кода может вести к сложности читаемости кода, в особенности если над кодом работать будут и другие разработчики. При рефакторинге стоит учитывать то, что метод должен вмещаться в 20 строк кода и максимум в один экран, в случаи разрастания кода следует метод разделять на под методы, это уменьшит их, упростит процедуру отладки, а другим программистам сократит время на понимание логики. Так же при работе с операторами выбора, такими как switch не стоит злоупотреблять, в программе, а лучше всего их заменить на словари Directionary, а так же Делегаты. Используйте StringBuilder над String, чтобы получить лучшую производительность: Есть целый ряд статей и сообщений , которые говорят , что StringBuilderявляется более эффективным , поскольку он содержит изменяемый буфер строки. .NET Строки неизменны, что является причиной , почему новый Stringобъект создается каждый раз , когда мы изменяем его (вставка, Append, удалить и т.д.). В следующем разделе я объясню это более подробно, чтобы дать новичкам четкое представление об этом факте. Я написал следующий код, и , как вы можете видеть, я определил Stringпеременную и StringBuilderпеременную. Я затем добавить строку в обоих этих переменных: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace StringTest { class Program { static void Main(string[] args) { string s = "Pranay"; s += " rana"; s += " rana1"; s += " rana122"; StringBuilder sb = new StringBuilder(); sb.Append("pranay"); sb.Append(" rana"); } } } Если разобрать этот код под рефлетором станет понятно по какой причине лучше использовать StringBuilder. Если вы зашли в рефлектор можете видеть, Concatфункция принимает два аргумента и возвращает String. Следующие шаги выполняются , когда мы выполняем Append с типом строки: 1. Проверяет, является ли строка пустой или нет 2. Создает строку destи выделяет память для строки 3. Заполняет destстроку str0иstr1 4. Возвращает destстроку, которая представляет собой новую переменную строку Таким образом, это доказывает, что всякий раз, когда я делаю операцию конкатенации строк, он создает новую строку из-за неизменное поведение строк. Функция Append принимает аргумент типа Stringи возвращает StringBuilderобъект. Следующие шаги выполняются , когда мы выполняем Appendс StringBuilderтипом: 1. Получить значение строки из StringBuilderобъекта 2. Проверьте, если требуется выделить память для новой строки мы будем добавлять 3. Выделение памяти при необходимости и добавить строку 4. Если не требуется, чтобы выделить память, а затем добавить строку непосредственно к существующей выделенной памяти 5. Возвращает StringBuilderобъект , который вызывает функцию, используя thisключевое слово Таким образом, она возвращает тот же объект, не создавая новый. Я надеюсь , что этот пример помог вам понять внутренние детали о том, почему мы должны использовать StringBuilderчаще чем , Stringчтобы получить более высокую производительность , когда мы делаем основную обработку строк в коде. Структура инициализации в C # Структуры в C # позволяют нам группировать переменные и методы. Они несколько похожи на классы, но есть ряд отличий между ними. В этой статье я не буду обсуждать это. Я собираюсь объяснить, как инициализировать структуру. факты 1. Структура является типом значения 2. Это не позволяет создать параметр меньше конструктора, поскольку он инициализирует переменную со значениями по умолчанию Теперь рассмотрим ниже случай, когда я создал две структуры: Структура 1: с открытыми переменными. 1 2 3 4 5 public struct StructMember { public int a; public int b; } Структура 2: со свойствами. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 public struct StructProperties { private int a; private int b; public int A { get { return a; } set { a = value; } } public int B { get { return b; } set 19 20 21 { b = value; } } } Учитывая вышеуказанные два факта, я пытался использовать обе структуры, как показано ниже: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 public class MainClass { public static void Main() { StructMembers MembersStruct; StructProperties PropertiesStruct; MembersStruct.X = 100; MembersStruct.Y = 200; PropertiesStruct.X = 100; PropertiesStruct.Y = 200; } } После этого, когда я пытаюсь скомпилировать код, я получаю сообщение об ошибке. C # компилятор сообщает нам, что позволяет использовать первую структуру без ошибок, но не позволяет использовать вторую структуру, которая выставляет свойство. Чтобы решить эту проблему, я написал ниже строки кода для инициализации второй структуры: 1 StructProperties PropertiesStruct = new StructProperties(); Дело в том, что структура может быть реализована без использования newоператора. Если вы не используете new, то поля будут оставаться Unassigned и объект не может использоваться , пока все поля не инициализированы. В .NET, все простые типы структур когда вы пишете код на C # необходимо инициализировать, рассмотрим случай ниже, где я создаю целочисленную переменную: 1 2 int a; Console.WriteLine(a); Компилятор выдает ошибку, что вы не можете использовать переменную без инициализации. Так что вам нужно написать либо: 1 int a =0; или же Используйте новый оператор для вызова конструктора по умолчанию и присвоить значение по умолчанию для переменной 1 int a = new >int(); Это очень важно, чтобы инициализировать структуру правильно. Оператор Checked В следующем разделе я буду объяснять о Checked оператора доступна в C # .NET для обработки целочисленных переполнений. В моей системе управления заказами, я должен вычислить точку продаж для каждого клиента, который размещает заказ. Пункты продажи являются целыми числами, которые получают заработанные клиент на основе продуктов, которые они покупают, и получает вычитаются из общей суммы счета, как они покупают новые продукты, используя эти точки. Но есть некоторые клиенты, которые не знают о балльной системе или не потребляют эти точки так, что точки накапливают более чем предел целочисленных переменных, то есть, 2 ^ 32. Таким образом, всякий раз, когда расчет происходит, я получаю некоторое значение опасное для тех клиентов, которые имеют значение точек больше, чем максимально допустимые целочисленное значение. Чтобы избежать этой проблемы переполнения целых значений и информировать клиентов о своих точках, я использую Checked оператор C # .NET. Проверено оператор для проверки на переполнение в математических операциях и переходах для целочисленных типов. Синтаксис 1 Checked( expression ) 1 Checked { statements...... } 1 2 public static void Main() { 3 4 5 6 7 8 9 10 11 int a; int b; int c; a = 2000000000; b = 2000000000; c = checked(a+ b); System.Console.WriteLine(Int1PlusInt2); } Когда мы запустим код выше, он бросает исключение. который говорит , что cбольше , чем максимально допустимое целочисленное значение. Точно так же, в моем приложении, я ловлю исключение переполнения брошенного при расчете точке заказа, с и затем отправить почту клиенту с напоминанием о необходимости использовать очки. GO TO Switch..Case Go To Идти к.. Позволяет нам прыгать безоговорочно, когда это требуется и не рекомендуется для использования в большой степени. Switch..Case Позволяет выполнить Caseблок на основе значения переменной, то есть, позволяет сделать программирование на основе условий. В моем приложении, я достиг той стадии , когда я должен был выполнить код Case 1из Switch..Caseи если какое — то условие было выполнено, я должен был выполнить код Case 3из Switch..Case. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 Switch(myvariable) { case 1: //statements …........ if ( expression ) execute case 3: break; case 2: ….. break; case 3: …...... break; } Первое решение этой проблемы , чтобы скопировать код Case 3и поместить его в ifблоке Case 1. 1 2 3 4 5 6 case 1: //statements …........ if ( expression ) //code of case 3 break; Но проблема выше решения заключается в том, что он делает избыточный код. Второе решение заключается в создании функции и поместить код в том , а затем выполнить код. 1 2 3 4 5 6 7 8 9 10 11 case 1: //statements …........ if ( expression ) Case3Code(); break; function Case3Code() { …. } Проблема с этим решением является то, что я должен создать дополнительную функцию, которая не нужна. Третье решение , чтобы сделать использование Go Toв Switch..Caseблоке: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 switch(MyVariable) { case 1: //statements …........ if ( expression ) goto case 3: break; case 2: ….. break; case 3: …...... break; } Go toВ Switch..Caseпозволяет мне сделать код легко и в обслуживаемой образом. Практическая работа №26 Создание приложения с БД Создание простого приложения для работы с данными с помощью ADO.NET 23.08.2017 Чтение занимает 12 мин o o o o При создании приложения, которое работает с данными в базе данных, необходимо выполнить такие основные задачи, как определение строк подключения, вставка данных и выполнение хранимых процедур. В этом разделе вы узнаете, как взаимодействовать с базой данных из простого Windows Forms приложения "формы по данным" с помощью Visual C#, Visual Basic и ADO.NET. Все технологии данных .NET, в том числе наборы данных, LINQ to SQL и Entity Framework, в конечном итоге выполняют шаги, которые очень похожи на те, которые приведены в этой статье. В этой статье демонстрируется простой способ быстрого получения данных из базы данных. Если приложению необходимо изменить данные с помощью нетривиальных способов и обновить базу данных, следует рассмотреть возможность использования Entity Framework и привязки данных для автоматической синхронизации элементов управления пользовательского интерфейса с изменениями в базовых данных. Важно! С целью упрощения код не включает обработку исключений для выполнения в рабочей среде. Предварительные требования Для создания приложения вам потребуются следующие компоненты. приведенному. SQL Server Express LocalDB. Если у вас нет SQL Server Express LocalDB, его можно установить на странице загрузки SQL Server Express. В этом разделе предполагается, что вы знакомы с базовой функциональностью интегрированной среды разработки Visual Studio и можете создать Windows Forms приложение, добавить формы в проект, поместить кнопки и другие элементы управления в формы, задать свойства элементов управления и создать код для простых событий. Если вы не знакомы с этими задачами, мы рекомендуем выполнить инструкции по началу работы с Visual C# и Visual Basic , прежде чем приступать к этому пошаговому руководству. Настройка образца базы данных Создайте образец базы данных, выполнив следующие действия. 1. В Visual Studio откройте окно Обозреватель сервера . 2. Щелкните правой кнопкой мыши подключения к данным и выберите команду создать новую базу данных SQL Server. 3. В текстовом поле имя сервера введите (LocalDB) \mssqllocaldb. 4. В текстовом поле имя новой базы данных введите Sales, а затем нажмите кнопку ОК. Пустая база данных Sales создается и добавляется в узел подключения к данным в обозреватель сервера. 5. Щелкните правой кнопкой мыши подключение к данным о продажах и выберите создать запрос. Откроется окно редактора запросов. 6. Скопируйте скрипт Transact-SQL Sales в буфер обмена. 7. Вставьте скрипт T-SQL в редактор запросов, а затем нажмите кнопку выполнить . По истечении короткого времени выполнение запроса завершается и создаются объекты базы данных. База данных содержит две таблицы: Customer и Orders. Эти таблицы изначально не содержат данных, но их можно добавить при запуске создаваемого приложения. База данных также содержит четыре простые хранимые процедуры. Создание форм и добавление элементов управления 1. Создайте проект для приложения Windows Forms и назовите его SimpleDataApp. Visual Studio создает проект и несколько файлов, включая пустую форму Windows Forms с именем Form1. 2. Добавьте две формы Windows Forms в проект, чтобы он включал три формы, и назначьте им следующие имена: o |