В настоящата глава ще разгледаме някои хитрости, хакове и техники, които ще улеснят работата ни с езика C# в среда за разработка Visual Studio. По-специално ще се запознаем:
- Как правилно да форматираме код
- С конвенции за именуване на елементи от код
- С някои бързи клавиши (keyboard shortcuts)
- С някои шаблони с код (code snippets)
- С техники за дебъгване на код
Правилното форматиране на нашия код ще го направи по-четим и разбираем, в случай че се наложи някой друг да работи с него. Това е важно, защото в практиката ще ни се наложи да работим в екип с други хора и е от голямо значение дали пишем кода си така, че колегите ни да могат бързо да се ориентират в него.
Има определени правила за правилно форматиране на кода, които събрани в едно се наричат конвенции. Конвенциите са група от правила, общоприети от програмистите на даден език, и се ползват масово. Тези конвенции помагат за изграждането на норми в дадени езици - как е най-добре да се пише и какви са добрите практики. Приема се, че ако един програмист ги спазва, то кодът му е лесно четим и разбираем.
Езикът C# е направен от Microsoft и те са тези, които определят най-добрите практики за писане. Трябва да знаете, че дори да не спазвате конвенциите, наложени от Microsoft, кодът ви ще работи (стига да е написан правилно), но просто няма да бъде лесно разбираем. Това, разбира се, не е фатално на основно ниво, но колкото по-бързо свикнете да пишете качествен код, толкова по-добре.
Официалната C# код конвенция на Microsoft е публикувана в статията "C# Coding Conventions" в MSDN (https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/inside-a-program/coding-conventions) и в тази книга ще се ръководим основно от нея.
За форматиране на кода от Microsoft се препоръчва къдравите скоби {}
да са на отделен ред и точно под конструкцията, към която се отнасят, както е в примера по-долу.
if (someCondition)
{
Console.WriteLine("Inside the if statement");
}
Вижда се, че командата Console.WriteLine(…)
в примера е 4 празни полета навътре (един таб), което също се препоръчва от Microsoft. Също така, ако дадена конструкция с къдрави скоби е един таб навътре, то къдравите скоби {}
трябва да са в началото на конструкцията, както е в примера по-долу:
if (someCondition)
{
if (anotherCondition)
{
Console.WriteLine("Inside the if statement");
}
}
Ето това е пример за лошо форматиран код спрямо общоприетите конвенции за писане на код на езика C#:
if(someCondition){
Console.WriteLine("Inside the if statement");}
Първото, което се забелязва са къдравите скоби {}
. Първата (отваряща) скоба трябва да е точно под if
условието, a втората (затваряща) скоба - под командата Console.WriteLine(…)
, на отделен празен ред. В допълнение, командата вътре в if
конструкцията трябва да бъде 4 празни полета навътре (един таб). Веднага след ключовата дума if
и преди условието на проверката се оставя интервал.
Същото правило важи и за for
цикли и всякакви други конструкции с къдрави скоби {}
. Ето още няколко примера:
Правилно:
for (int i = 0; i < 5; i++)
{
Console.WriteLine(i);
}
Грешно:
for(int i=0;i<5;i++){
Console.WriteLine(i);
}
За ваше удобство има бързи клавиши във Visual Studio, за които ще обясним по-късно в настоящата глава, но засега ни интересуват 2 конкретни комбинации. Едната комбинация е за форматиране на кода в целия документ, а другата комбинация - за форматиране на част от кода. Ако искаме да форматираме целия код, то трябва да натиснем [CTRL + K + D]. В случай, че искаме да форматираме само част от кода, то ние трябва да маркираме с мишката частта, която искаме да форматираме, и да натиснем [CTRL + K + F].
Нека използваме грешния пример от преди малко:
for(int i=0;i<5;i++){
Console.WriteLine(i);
}
Ако натиснем [CTRL + K + D], което е нашата комбинация за форматиране на целия документ, ще получим код, форматиран според общоприетите конвенции за C#, който ще изглежда по следния начин:
for (int i = 0; i < 5; i++)
{
Console.WriteLine(i);
}
Тази комбинация може да ни помогне, ако попаднем на лошо форматиран код.
В тази секция ще се фокусираме върху общоприетите конвенции за именуване на проекти, файлове и променливи, наложени от Microsoft.
За именуване на проекти и файлове се препоръчва описателно име, което подсказва каква е ролята на въпросния файл / проект и в същото време се препоръчва PascalCase
конвенцията. Tова е конвенция за именуване на елементи, при която всяка дума, включително първата, започва с главна буква, например ExpressionCalculator
.
Пример: в този курс се започва с лекция на име First steps in coding и следователно едно примерно именуване на проекта (solution) за тази лекция може да бъде FirstStepsInCoding
. Същата конвенция важи и за файловете в даден проект. Ако вземем за пример първата задача от лекцията First steps in coding, тя се казва Hello World и следователно нашият файл в проекта ще се казва HelloWorld
.
В програмирането променливите пазят някакви данни и за да е по-разбираем кода, името на една променлива трябва да подсказва нейното предназначение. Ето и още няколко препоръки за имената на променливите:
- Името трябва да е кратко и описателно и да обяснява за какво служи дадената променлива.
- Името трябва да се състои само от буквите a-z, A-Z, цифрите 0-9, както и символа '_'.
- В C# е прието променливите да започват винаги с малка буква и да съдържат малки букви, като всяка следваща дума в тях започва с главна буква (това именуване е още познато като
camelCase
конвенция). - Трябва да се внимава за главни и малки букви, тъй като C# прави разлика между тях. Например
age
иAge
са различни променливи. - Имената на променливите не могат да съвпадат със служебна дума (keyword) от езика C#, например
int
е невалидно име на променлива.
Въпреки че използването на символа _ в имената на променливите е разрешено, в C# това не се препоръчва и се счита за лош стил на именуване. |
Ето няколко примера за добре именувани променливи:
firstName
age
startIndex
lastNegativeNumberIndex
Ето няколко примера за лошо именувани променливи, макар и имената да са коректни от гледна точка на компилатора на C#:
_firstName
(започва с '_')last_name
(съдържа '_')AGE
(изписана е с главни букви)Start_Index
(започва с главна буква и съдържа '_')lastNegativeNumber_Index
(съдържа '_')
Първоначално всички тези правила може да ни се струват безсмислени и ненужни, но с течение на времето и натрупването на опит ще видите нуждата от норми за писане на качествен код, за да може да се работи по-лесно и по-бързо в екип. Ще разберете, че е изключително досадна работата с код, който е написан без да се спазват никакви правила за качествен код.
В предната секция споменахме за две от комбинациите, които се отнасят за форматиране на код. Едната комбинация [CTRL + K + D] беше за форматиране на целия код в даден файл, а втората [CTRL + K + F] ни служеше в случай, че искаме да форматираме само дадена част от кода. Тези комбинации се наричат бързи клавиши и сега ще дадем по-подробна информация за тях.
Бързи клавиши са комбинации, които ни предоставят възможността да извършваме някои действия по-лесно и по-бързо, като всяка среда за разработка на софтуер си има своите бързи клавиши, въпреки че повечето се повтарят. Сега ще разгледаме някои от бързите клавиши във Visual Studio.
Комбинация | Действие |
---|---|
[CTRL + F] | Комбинацията отваря търсачка, с която можем да търсим в нашия код. |
[CTRL + K + C] | Закоментира част от кода. |
[CTRL + K + U] | Разкоментира код, който е вече закоментиран. |
[CTRL + Z] | Връща една промяна назад (т.нар. Undo). |
[CTRL + Y] | Комбинацията има противоположно действие на [CTRL + Z] (т.нар. Redo). |
[CTRL + K + D] | Форматира кода според конвенциите по подразбиране. |
[CTRL + Backspace] | Изтрива думата вляво от курсора. |
[CTRL + Del] | Изтрива думата вдясно от курсора. |
[CTRL + Shift + S] | Запазва всички файлове в проекта. |
[CTRL + S] | Запазва текущия файл. |
Повече за бързите клавиши във Visual Studio може да намерите тук: https://shortcutworld.com/en/Visual-Studio/2015/win/all.
Във Visual Studio съществуват т.нар. шаблони с код (code snippets), при изписването на които се изписва по шаблон някакъв блок с код. Примерно, при изписването на кратък код “cw
” и натискане на [Tab] + [Tab] се генерира кодът Console.WriteLine();
в тялото на нашата програма, на мястото на краткия код. Това се нарича “разгъване на шаблон за кратък код”. Подобно работи и шаблона “for
” + [Tab] + [Tab]. На фигурата по-долу е показано действието на шаблона “cw
”:
В тази секция ще покажем как сами да си направим собствен шаблон. Ще разгледаме как се прави code snippet за Console.ReadLine()
. Като за начало ще си създадем нов празен проект и ще отидем на [Tools -> Code Snippets Manager], както е показано на снимката:
В отворилия се прозорец трябва да изберем Language -> CSharp, а от секцията Locations -> Visual C#. Там се намират всички съществуващи шаблони за езика C#:
Избираме някой snippet, например cw
, вземаме пътя до неговия файл и го отваряме с редактора на Visual Studio:
Виждаме доста непознати неща, но няма страшно, по-нататък ще се запознаем и с тях. Сега се фокусираме върху частта <Title><Title>
, <Shortcut><Shortcut>
и кода между CDATA[]
. Първо ще сменим заглавието, което седи в секцията <Title><Title>
и вместо cw
, ще напишем cr
, като това ще бъде заглавието на нашия шаблон. След това, в секцията <Shortcut><Shortcut>
, ще сменим това, което трябва да напишем за извикването на нашия шаблон (shortcut) от cw
на cr
. Накрая трябва да сменим кода в CDATA[]
, от WriteLine
на ReadLine
: CDATA[$SystemConsole$.ReadLine($end$);]
. Пожелание може да промените и секциите Description и Author. Промененият файл трябва да изглежда така:
След като сме написали нашия snippet, трябва да си запазим файла във формат snippetName.snippet
(в нашия случай cr.snippet
) и да го добавим към Visual Studio. Отиваме в [Tools] -> [Code Snippet Manager] -> [Import] и избираме cr.snippet
файла, който създадохме:
Вече когато напишем cr
във Visual Studio, нашият нов snippet се появява:
Дебъгването играе важна роля в процеса на създаване на софтуер, която ни позволява постъпково да проследим изпълнението на нашата програма. С помощта на тази техника можем да следим стойностите на локалните променливи, тъй като те се променят по време на изпълнение на програмата, и да отстраним евентуални грешки (бъгове). Процесът на дебъгване включва:
- Забелязване на проблемите (бъговете).
- Намиране на кода, който причинява проблемите.
- Коригиране на кода, причиняващ проблемите, така че програмата да работи правилно.
- Тестване, за да се убедим, че програмата работи правилно след нанесените корекции.
Visual Studio ни предоставя вграден дебъгер (debugger), чрез който можем да поставяме точки на прекъсване (или breakpoints), на избрани от нас места. При среща на стопер (breakpoint), програмата спира изпълнението си и позволява постъпково изпълнение на останалите редове. Дебъгването ни дава възможност да вникнем в детайлите на програмата и да видим къде точно възникват грешките и каква е причината за това.
За да демонстрираме работа с дебъгера ще използваме следната програма:
static void Main(string[] args)
{
for (int i = 0; i < 100; i++)
{
Console.WriteLine(i);
}
}
Ще сложим стопер (breakpoint) на функцията Console.WriteLine(…)
. За целта трябва да преместим курсора на реда, който печата на конзолата, и да натиснем [F9]. Появява се стопер, където програмата ще спре изпълнението си:
За да стартираме програмата в режим на дебъгване, избираме [Debug] -> [Start Debugging] или натискаме [F5]:
След стартиране на програмата виждаме, че тя спира изпълнението си на ред 11, където сложихме стопера (breakpoint). Кодът на текущия ред се оцветява с жълт цвят и можем да го изпълняваме постъпково. За да преминем на следващ ред използваме клавиш [F10]. Забелязваме, че кодът на текущия ред все още не е изпълнен. Изпълнява се, когато преминем на следващия ред:
От прозореца Locals можем да наблюдаваме промените по локалните променливи. За да отворите прозореца изберете [Debug] -> [Windows] -> [Locals].
В тази секция ще припомним накратко хитрости и техники от програмирането с езика C#, разглеждани вече в тази книга, които ще са ви много полезни, ако ходите на изпит по програмиране за начинаещи:
var text = "some text";
Console.WriteLine("{0}", text);
// Tова ще отпечата на конзолата "some text"
В случая използваме placeholder - {x}
, където x е число (по-голямо или равно на 0), отговарящо на позицията, на която трябва да поставим променливата. Следователно, ако подаваме две променливи ще имаме един placeholder, който ще е {0}
и той ще съдържа стойността на първата променлива и още един - {1}
, който ще съдържа стойността на втората променлива. Примерно:
var text = "some text";
var number = 5;
Console.WriteLine("{0} {1} {0}", text, number);
// Tова ще отпечата "some text 5 some text"
В този пример забелязваме, че можем да подаваме не само текстови променливи. Също така можем да използваме дадена променлива няколко пъти и за целта в placeholder-а слагаме числото, което отговаря на позицията на променливата. В случая на нулева позиция стои променливата text
, а на първа позиция е променливата number
. Номерацията е объркваща отначало, но трябва да запомните, че в програмирането броенето започва от 0.
var number = 5.432432;
Console.WriteLine(Math.Round(number, 2));
// Това ще отпечата на конзолата "5.43"
Math.Round(…)
приема 2 параметъра:
- първият е числото, което искаме да закръглим
- вторият е числото, което определя с колко символа след десетичния знак ще закръглим (това число винаги трябва да бъде цяло число)
Ако искаме да закръглим до 2 цифри след десетичния знак и третата цифра е по-малкa от 5, както в примера по-горе, то закръглянето е надолу, но ако третата цифра е 5 или по-голяма - закръглянето е нагоре, както е в примера по-долу:
var number = 5.439;
Console.WriteLine(Math.Round(number, 2));
// Tова ще отпечата на конзолата "5.44"
В случай, че искаме винаги да закръгляме надолу можем вместо Math.Round(…)
да използваме друг метод - Math.Floor(…)
, който винаги закръгля надолу, но също така винаги закръгля до цяло число. Например, ако имаме числото 5.99 и използваме Math.Floor(5.99)
, ще получим числото 5.
Можем и да направим точно обратното - винаги да закръгляме нагоре, използвайки метода Math.Ceiling(…)
. Отново, ако имаме число примерно 5.11 и използваме Math.Ceiling(5.11)
, ще получим 6. Ето и няколко примера:
var numberToFloor = 5.99;
Console.WriteLine(Math.Floor(numberToFloor));
// Tова ще отпечата на конзолата 5
var numberToCeiling = 5.11;
Console.WriteLine(Math.Ceiling(numberToCiling));
// Tова ще отпечата на конзолата 6
var num = 5.432424;
Console.WriteLine("{0:f2}", num);
В случая след числото добавяме :f2
, което ще ограничи числото до 2 цифри след десетичния знак и ще работи като Math.Round(…)
. Трябва да имаме предвид, че числото след буквата f
означава до колко цифри след десетичния знак да е закръглено числото (т.е. може да е примерно f3
или f5
).
Условната if
конструкция се състои от следните елементи:
- Ключова дума
if
- Булев израз (условие)
- Тяло на условната конструкция
- Незадължително:
else
клауза
if (условие)
{
// тяло
}
else (условие)
{
// тяло
}
За улеснение може да използваме code snippet за if
конструкция:
if
+ [Tab] + [Tab]
За for
цикъл ни трябват няколко неща:
- Инициализационен блок, в който се декларира променливата-брояч (
var i
) и се задава нейна начална стойност. - Условие за повторение (
i <= 10
). - Обновяване на брояча (
i++
). - Тяло на цикъла.
for (var i = 0; i < 5; i++;)
{
// тяло
}
За улеснение може да използваме code snippet за for
цикъл:
for
+ [Tab] + [Tab]
В настоящата глава се запознахме как правилно да форматираме и именуваме елементите на нашия код, някои бързи клавиши (shortcuts) за работа във Visual Studio, шаблони с код (code snippets) и разгледахме как се дебъгва код.