В настоящата глава ще разгледаме някои хитрости, хакове и техники, които ще улеснят работата ни с езика C# в среда за разработка Visual Studio. По-специално ще се запознаем:
- Как правилно да форматираме код
- С конвенции за именуване на елементи от код
- С някои бързи клавиши (keyboard shortcuts)
- С някои шаблони с код (code snippets)
- С техники за дебъгване на код
Правилното форматиране на нашия код ще го направи по-четим и разбираем, в случай че се наложи някой друг да работи с него. Това е важно, защото в практиката ще ни се наложи да работим в екип с други хора и е от голямо значение дали пишем кода си така, че колегите ни да могат бързо да се ориентират в него.
Има определени правила за правилно форматиране на кода, които събрани в едно се наричат конвенции. Конвенциите са група от правила, общоприети от програмистите на даден език, и се ползват масово. Тези конвенции помагат за изграждането на норми в дадени езици - как е най-добре да се пише и какви са добрите практики. Приема се, че ако един програмист ги спазва, то кодът му е лесно четим и разбираем. Езикът C# е направен от Microsoft и те са тези, които определят най-добрите практики за писане. Трябва да знаете също така, че дори да не спазвате конвенциите, наложени от Microsoft, кодът ви ще работи (стига да е написан правилно), но просто няма да бъде лесно разбираем. Това, разбира се, не е фатално на основно ниво, но колкото по-бързо свикнете да пишете качествен код, толкова по-добре.
За форматиране на кода от Microsoft се препоръчва къдравите скоби {}
да са на отделен ред и точно под конструкцията, към която се отнасят, както е в примера по-долу.
if (true)
{
Console.WriteLine("влязох в if-a");
}
Вижда се, че командата Console.WriteLine(...)
в примера е 4 празни полета навътре (един таб), което също се препоръчва от Microsoft. Също така, ако дадена конструкция с къдрави скоби е един таб навътре, то къдравите скоби {}
трябва да са в началото на конструкцията, както е в примера по-долу:
if (true)
{
if (true)
{
Console.WriteLine("влязох в if-a");
}
}
Ето това е пример за лошо форматиран код спрямо общоприетите конвенции за писане на код на езика C#:
if(true){
Console.WriteLine("влязох в if-a");}
Първото, което се забелязва са къдравите скоби {}
. Първата (отваряща) скоба трябва да е точно под if
условието, a втората (затваряща) скоба - под командата Console.WriteLine(...)
, на отделен празен ред. В допълнение, командата вътре в if
конструкцията трябва да бъде 4 празни полета навътре (един таб). Същото правило важи и за 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.
За именуване на проекти и файлове се препоръчва описателно име, което подсказва каква е ролята на въпросния файл/проект и в същото време се препоръчва Upper Camel Case конвенцията. Накратко, това е конвенция за именуване на елементи, при която всяка дума, включително първата, започва с главна буква. Пример: в този курс се започва с лекция на име First steps in coding и следователно едно примерно именуване на проекта (solution) за тази лекция може да бъде FirstStepsInCoding. Същата конвенция важи и за файловете в даден проект. Ако вземем за пример първата задача от лекцията First steps in coding, тя се казва Hello World и следователно нашият файл в проекта ще се казва HelloWorld.
Нещата стоят по по-различен начин при променливи. Правилaта за именуване на променливи гласят, че:
- Името трябва да е кратко и описателно и да обяснява за какво служи дадената променлива.
- Името трябва да се състои само от буквите a-z, A-Z, цифрите 0-9, както и символа '_'.
- В C# е прието променливите да започват винаги с малка буква и да съдържат малки букви, като всяка следваща дума в тях започва с главна буква (това е още познато като Lower Camel Case).
- Трябва да се внимава за главни и малки букви, тъй като C# прави разлика между тях. Например
age
иAge
са различни променливи.
Въпреки че е разрешено използването на символа _ в имената на променливите, се счита за лош стил на именуване. |
Ето няколко примера за добре именувани променливи:
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 Studiо съществуват т.нар. шаблони с код (code snippets), при изписването на които се генерира шаблон с код. Примерно при изписването на [cw
+ Tab + Tab]" се генерира кодът Console.WriteLine(...);
:
В тази подглава ще покажем как сами да си направим собствен шаблон. Ще разгледаме как се прави code snippet за Console.ReadLine()
. Като за начало ще си създадем нов празен проект и ще отидем на [Tools -> Code Snippet Manager], както е показано на снимката:
В отворилия се прозорец трябва да изберем Language -> CSharp, а от секцията Locations -> Visual C#. Там се намират всички съществуващи шаблони за езика C#:
Избираме някой snippet, например cw
, вземаме пътя му и го отваряме:
Виждаме доста непознати неща, но няма страшно, по-нататък ще се запознаем и с тях. Сега се фокусираме върху частта <Title><Title>
, <Shortcut><Shortcut>
и кода между CDATA[]
. Първо ще сменим заглавието, което седи в секцията <Title><Title>
и вместо cw
, ще напишем cr
, като това ще бъде заглавието на нашия шаблон. След това, в секцията <Shortcut><Shortcut>
, ще сменим това, което трябва да напишем за извикването на нашия шаблон (shortcut) от cw
на cr
. Накрая трябва да сменим кода в CDATA[]
, от WriteLine
на ReadLine
: CDATA[$SystemConsole$.ReadLine($end$);]
. Пожелание може да промените и секциите Description и Author. Промененият файл трябва да изглежда така:
След като сме написали нашия snippet, трябва да си запазим файла във формат snippName.snippet (в нашия случай cr.snippet). За да вкараме shortcut комбинацията в Visual Sudio отиваме в [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].
Тази подглава ще съдържа някои основни и полезни неща, разглеждани в тази книга:
var text = "some text"
Console.WriteLine("{0}", text);
// това ще изкара на конзолата "some text"
В случая използваме placeholder - {x}
, където x е число (по-голямо или равно на 0), отговарящо на позицията, на която трябва да поставим променливата. Следователно, ако подаваме 2 променливи ще имаме един placeholder, който ще е {0}
и той ще съдържа стойността на първата променлива и още един - {1}
, който ще съдържа стойността на втората променлива. Примерно:
var text = "some text"
var number = 5;
Console.WriteLine("{0} {1} {0}", text, number);
// това ще изкара "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));
// това ще изкара на конзолата "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;
var numberToCeiling = 5.11;
Console.WriteLine(Math.Floor(numberToFloor)); // това ще изкара на конзолата 5
Console.WriteLine(Math.Ceiling(numberToCiling)); // това ще изкара на конзолата 6
var num = 5.432424";
Console.WriteLine("{0:f2}",num);
В случая след числото добавяме :f2
, което ще ограничи числото до 2 цифри след десетичния знак и ще работи като Math.Round(...)
. Tрябва да имаме предвид, че числото след буквата 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) и разгледахме как се дебъгва код.