СДЕЛАЙТЕ СВОИ УРОКИ ЕЩЁ ЭФФЕКТИВНЕЕ, А ЖИЗНЬ СВОБОДНЕЕ

Благодаря готовым учебным материалам для работы в классе и дистанционно

Скидки до 50 % на комплекты
только до

Готовые ключевые этапы урока всегда будут у вас под рукой

Организационный момент

Проверка знаний

Объяснение материала

Закрепление изученного

Итоги урока

Основы програмирования на C#

Категория: Информатика

Нажмите, чтобы узнать подробности

Просмотр содержимого документа
«Основы програмирования на C#»

Тема: Основы программирования на C#

Структура программы

Инструкции

Базовым строительным блоком программы являются инструкции (statement). Инструкция представляет некоторое действие, например, арифметическую операцию, вызов метода, объявление переменной и присвоение ей значения. В конце каждой инструкции в C# ставится точка с запятой (;). Данный знак указывает компилятору на конец инструкции. Например:

1

Console.WriteLine("Привет");

Данная строка представляет вызов метода Console.WriteLine, который выводит на консоль строку. В данном случае вызов метода является инструкцией и поэтому завершается точкой с запятой.

Набор инструкций может объединяться в блок кода. Блок кода заключается в фигурные скобки, а инструкции помещаются между открывающей и закрывающей фигурными скобками:

1

2

3

4

{

    Console.WriteLine("Привет");

    Console.WriteLine("Добро пожаловать в C#");

}

В данном блоке кода две инструкции, которые выводят на консоль определенную строку.

Одни блоки кода могут содержать другие блоки:

1

2

3

4

5

6

{

    Console.WriteLine("Первый блок");

    {

        Console.WriteLine("Второй блок");

    }

}

Метод Main

Точкой входа в программу на языке C# является метод Main. При создании проекта консольного приложения в Visual Studio, например, создается следующий метод Main:

1

2

3

4

5

6

7

class Program

{

    static void Main(string[] args)

    {

        // здесь помещаются выполняемые инструкции

    }

}

По умолчанию метод Main размещается в классе Program. Название класса может быть любым. Но метод Main является обязательной частью консольного приложения. Если мы изменим его название, то программа не скомпилируется.

По сути и класс, и метод представляют своего рода блок кода: блок метода помещается в блок класса. Внутри блока метода Main располагаются выполняемые в программе инструкции.

Регистрозависимость

C# является регистрозависимым языком. Это значит, в зависимости от регистра символов какое-то определенные названия может представлять разные классы, методы, переменные и т.д. Например, название обязательного метода Main начинается именно с большой буквы: "Main". Если мы назовем метод "main", то программа не скомпилируется, так как метод, который представляет стартовую точку в приложении, обязательно должен называться "Main", а не "main" или "MAIN".

Комментарии

Важной частью программного кода являются комментарии. Они не являются собственно частью программы, при компиляции они игнорируются. Тем не менее комментарии делают код программы более понятным, помогая понять те или иные его части.

есть два типа комментариев: однострочный и многострочный. Однострочный комментарий размещается на одной строке после двойного слеша //. А многострочный комментарий заключается между символами /* текст комментария */. Он может размещаться на нескольких строках. Например:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

using System;

 

namespace HelloApp

{

    /*

        программа, которая спрашивает у пользователя имя

        и выводит его на консоль

    */

    class Program

    {

        // метод Main - стартовая точка приложения

        static void Main(string[] args)

        {

            Console.Write("Введите свое имя: ");

            string name = Console.ReadLine();       // вводим имя

        }

    }

}

Программы верхнего уровня

Начиная с версии C# 9.0 (.NET 5) добавлена возможность создавать программы верхнего уровня. То есть, если у нас программа состоит из одного метода Main, то мы можем убрать из определения программы объявление пространства имен (namespace HelloApp), объявление класса (class Program) и объявление метода Main (static void Main(string[] args)) и оставить только директивы using с подключаемыми пространствами имен и собственно исполняемые инструкции.

Например, выше в предыдущем листинге кода программа запрашивала ввод имени пользователя. Фактически все тело программы состоит из метода Main, поэтому мы ее можем сократить в C# 9.0 следующим образом:

1

2

3

4

5

using System;

 

Console.Write("Введите свое имя: ");

string name = Console.ReadLine();       // вводим имя

Console.WriteLine($"Привет {name}");    // выводим имя на консоль

Результат работы программы будет тот же, что и в предыдущем случае.

Переменные

Для хранения данных в программе применяются переменные. Переменная представляет именнованную область памяти, в которой хранится значение определенного типа. Переменная имеет тип, имя и значение. Тип определяет, какого рода информацию может хранить переменная.

Перед использованием любую переменную надо определить. Синтаксис определения переменной выглядит следующим образом:

1

тип имя_переменной;

Вначале идет тип переменной, потом ее имя. В качестве имени переменной может выступать любое произвольное название, которое удовлетворяет следующим требованиям:

  • имя может содержать любые цифры, буквы и символ подчеркивания, при этом первый символ в имени должен быть буквой или символом подчеркивания

  • в имени не должно быть знаков пунктуации и пробелов

  • имя не может быть ключевым словом языка C#. Таких слов не так много, и при работе в Visual Studio среда разработки подсвечивает ключевые слова синим цветом.

Хотя имя переменой может быть любым, но следует давать переменным описательные имена, которые будут говорить об их предназначении.

Например, определим простейшую переменную:

1

string name;

В данном случае определена переменная name, которая имеет тип string. то есть переменная представляет строку. Поскольку определение переменной представляет собой инструкцию, то после него ставится точка с запятой.

При этом следует учитывать, что C# является регистрозависимым языком, поэтому следующие два определения переменных будут представлять две разные переменные:

1

2

string name;

string Name;

После определения переменной можно присвоить некоторое значение:

1

2

string name;

name = "Tom";

Так как переменная name представляет тип string, то есть строку, то мы можем присвоить ей строку в двойных кавычках. Причем переменной можно присвоить только то значение, которое соответствует ее типу.

В дальнейшем с помощью имени переменной мы сможем обращаться к той области памяти, в которой хранится ее значение.

Также мы можем сразу при определении присвоить переменной значение. Данный прием называется инициализацией:

1

string name = "Tom";

Отличительной чертой переменных является то, что в программе можно многократно менять их значение. Например, создадим небольшую программу, в которой определим переменную, поменяем ее значение и выведем его на консоль:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

using System;

 

namespace HelloApp

{

    class Program

    {

        static void Main(string[] args)

        {

            string name = "Tom";  // определяем переменную и инициализируем ее

 

            Console.WriteLine(name);    // Tom

 

            name = "Bob";       // меняем значение переменной

            Console.WriteLine(name);    // Bob

 

            Console.Read();

        }

    }

}

Консольный вывод программы:

Tom

Bob

Литералы

Литералы представляют неизменяемые значения (иногда их еще называют константами). Литералы можно передавать переменным в качестве значения. Литералы бывают логическими, целочисленными, вещественными, символьными и строчными. И отдельный литерал представляет ключевое слово null.

Логические литералы

Есть две логических константы - true (истина) и false (ложь):

1

2

Console.WriteLine(true);

Console.WriteLine(false);

Целочисленные литералы

Целочисленные литералы представляют положительные и отрицательные целые числа, например, 1, 2, 3, 4, -7, -109. Целочисленные литералы могут быть выражены в десятичной, шестнадцатеричной и двоичной форме.

С целыми числами в десятичной форме все должно быть понятно, так как они используются в повседневной жизни:

1

2

3

Console.WriteLine(-11);

Console.WriteLine(5);

Console.WriteLine(505);

Числа в двоичной форме предваряются символами 0b, после которых идет набор из нулей и единиц:

1

2

3

Console.WriteLine(0b11);        // 3

Console.WriteLine(0b1011);      // 11

Console.WriteLine(0b100001);    // 33

Для записи числа в шестнадцатеричной форме применяются символы 0x, после которых идет набор символов от 0 до 9 и от A до F, которые собственно представляют число:

1

2

3

Console.WriteLine(0x0A);    // 10

Console.WriteLine(0xFF);    // 255

Console.WriteLine(0xA1);    // 161

Вещественные литералы

Вещественные литералы представляют вещественные числа. Этот тип литералов имеет две формы. Первая форма - вещественные числа с фиксированной запятой, при которой дробную часть отделяется от целой части точкой. Например:

1

2

3

3.14

100.001

-0.38

Также вещественные литералы могут определяться в экспоненциальной форме MEp, где M — мантисса, E - экспонента, которая фактически означает "*10^" (умножить на десять в степени), а p — порядок. Например:

1

2

Console.WriteLine(3.2e3);   // по сути равно 3.2 * 103 = 3200

Console.WriteLine(1.2E-1);  // равно 1.2 * 10-1 = 0.12

Символьные литералы

Символьные литералы представляют одиночные символы. Символы заключаются в одинарные кавычки.

Символьные литералы бывают нескольких видов. Прежде всего это обычные символы:

1

2

3

'2'

'A'

'T'

Специальную группу представляют управляющие последовательности.

 Управляющая последовательность представляет символ, перед которым ставится обратный слеш. И данная последовательность интерпретируется определенным образом. Наиболее часто используемые последовательности:

  • '\n' - перевод строки

  • '\t' - табуляция

  • '\' - обратный слеш

И если компилятор встретит в тексте последовательность \t, то он будет воспринимать эту последовательность не как слеш и букву t, а как табуляцию - то есть длинный отступ.

Также символы могут определяться в виде шестнадцатеричных кодов, также заключенный в одинарные кавычки.

Еще один способ определения символов представляет использования шестнадцатеричных кодов ASCII. Для этого в одинарных кавычках указываются символы '\x', после которых идет шестнадцатеричный код символа из таблицы ASCII. Коды символов из таблицы ASCII можно посмотреть здесь.

Например, литерал '\x78' представляет символ "x":

1

2

Console.WriteLine('\x78');    // x

Console.WriteLine('\x5A');    // Z

И последний способ определения символьных литералов представляет применение кодов из таблицы символов Unicode. Для этого в одинарных кавычках указываются символы '\u', после которых идет шестнадцатеричный код Unicode. Например, код '\u0411' представляет кириллический символ 'Б':

1

2

Console.WriteLine('\u0420');    // Р

Console.WriteLine('\u0421');    // С

Строковые литералы

Строковые литералы представляют строки. Строки заключаются в двойные кавычки:

1

2

3

Console.WriteLine("hello");

Console.WriteLine("фыва");

Console.WriteLine("hello word");

Если внутри строки необходимо вывести двойную кавычку, то такая внутренняя кавычка предваряется обратным слешем:

1

Console.WriteLine("Компания \"Рога и копыта\"");

Также в строках можно использовать управляющие последовательности. Например, последовательность '\n' осуществляет перевод на новую строку:

1

Console.WriteLine("Привет \nмир");

При выводе на консоль слово "мир" будет перенесено на новую строку:

Привет

мир

null

null представляет ссылку, которая не указывает ни на какой объект. То есть по сути отсутствие значения.

Типы данных

Как и во многих языках программирования, в C# есть своя система типов данных, которая используется для создания переменных. Тип данных определяет внутреннее представление данных, множество значений, которые может принимать объект, а также допустимые действия, которые можно применять над объектом.

В языке C# есть следующие примитивные типы данных:

  • bool: хранит значение true или false (логические литералы). Представлен системным типом System.Boolean

    1

    2

    bool alive = true;

    bool isDead = false;

  • byte: хранит целое число от 0 до 255 и занимает 1 байт. Представлен системным типом System.Byte

    1

    2

    byte bit1 = 1;

    byte bit2 = 102;

  • sbyte: хранит целое число от -128 до 127 и занимает 1 байт. Представлен системным типом System.SByte

    1

    2

    sbyte bit1 = -101;

    sbyte bit2 = 102;

  • short: хранит целое число от -32768 до 32767 и занимает 2 байта. Представлен системным типом System.Int16

    1

    2

    short n1 = 1;

    short n2 = 102;

  • ushort: хранит целое число от 0 до 65535 и занимает 2 байта. Представлен системным типом System.UInt16

    1

    2

    ushort n1 = 1;

    ushort n2 = 102;

  • int: хранит целое число от -2147483648 до 2147483647 и занимает 4 байта. Представлен системным типом System.Int32. Все целочисленные литералы по умолчанию представляют значения типа int:

    1

    2

    3

    int a = 10;

    int b = 0b101;  // бинарная форма b =5

    int c = 0xFF;   // шестнадцатеричная форма c = 255

  • uint: хранит целое число от 0 до 4294967295 и занимает 4 байта. Представлен системным типом System.UInt32

    1

    2

    3

    uint a = 10;

    uint b = 0b101;

    uint c = 0xFF;

  • long: хранит целое число от –9 223 372 036 854 775 808 до 9 223 372 036 854 775 807 и занимает 8 байт. Представлен системным типом System.Int64

    1

    2

    3

    long a = -10;

    long b = 0b101;

    long c = 0xFF;

  • ulong: хранит целое число от 0 до 18 446 744 073 709 551 615 и занимает 8 байт. Представлен системным типом System.UInt64

    1

    2

    3

    ulong a = 10;

    ulong b = 0b101;

    ulong c = 0xFF;

  • float: хранит число с плавающей точкой от -3.4*1038 до 3.4*1038 и занимает 4 байта. Представлен системным типом System.Single

  • double: хранит число с плавающей точкой от ±5.0*10-324 до ±1.7*10308 и занимает 8 байта. Представлен системным типом System.Double

  • decimal: хранит десятичное дробное число. Если употребляется без десятичной запятой, имеет значение от ±1.0*10-28 до ±7.9228*1028, может хранить 28 знаков после запятой и занимает 16 байт. Представлен системным типом System.Decimal

  • char: хранит одиночный символ в кодировке Unicode и занимает 2 байта. Представлен системным типом System.Char. Этому типу соответствуют символьные литералы:

    1

    2

    3

    char a = 'A';

    char b = '\x5A';

    char c = '\u0420';

  • string: хранит набор символов Unicode. Представлен системным типом System.String. Этому типу соответствуют строковые литералы.

    1

    2

    string hello = "Hello";

    string word = "world";

  • object: может хранить значение любого типа данных и занимает 4 байта на 32-разрядной платформе и 8 байт на 64-разрядной платформе. Представлен системным типом System.Object, который является базовым для всех других типов и классов .NET.

1

2

3

object a = 22;

object b = 3.14;

object c = "hello code";

Например, определим несколько переменных разных типов и выведем их значения на консоль:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

using System;

 

namespace HelloApp

{

    class Program

    {

        static void Main(string[] args)

        {

            string name = "Tom";

            int age = 33;

            bool isEmployed = false;

            double weight = 78.65;

             

            Console.WriteLine($"Имя: {name}");

            Console.WriteLine($"Возраст: {age}");

            Console.WriteLine($"Вес: {weight}");

            Console.WriteLine($"Работает: {isEmployed}");

        }

    }

}

Для вывода данных на консоль здесь применяется интерполяция: перед строкой ставится знак $ и после этого мы можем вводить в строку в фигурных скобках значения переменных. Консольный вывод программы:

Имя: Tom

Возраст: 33

Вес: 78,65

Работает: False

Использование суффиксов

При присвоении значений надо иметь в виду следующую тонкость: все вещественные литералы рассматриваются как значения типа double. И чтобы указать, что дробное число представляет тип float или тип decimal, необходимо к литералу добавлять суффикс: F/f - для float и M/m - для decimal.

1

2

3

4

5

float a = 3.14F;

float b = 30.6f;

 

decimal c = 1005.8M;

decimal d = 334.8m;

Подобным образом все целочисленные литералы рассматриваются как значения типа int. Чтобы явным образом указать, что целочисленный литерал представляет значение типа uint, надо использовать суффикс U/u, для типа long - суффикс L/l, а для типа ulong - суффикс UL/ul:

1

2

3

uint a = 10U;

long b = 20L;

ulong c = 30UL;

Использование системных типов

Выше при перечислении всех базовых типов данных для каждого упоминался системный тип. Потому что название встроенного типа по сути представляет собой сокращенное обозначение системного типа. Например, следующие переменные будут эквивалентны по типу:

1

2

int a = 4;

System.Int32 b = 4;

Неявная типизация

Ранее мы явным образом указывали тип переменных, например, int x;. И компилятор при запуске уже знал, что x хранит целочисленное значение.

Однако мы можем использовать и модель неявной типизации:

1

2

3

4

5

var hello = "Hell to World";

var c = 20;

             

Console.WriteLine(c.GetType().ToString());

Console.WriteLine(hello.GetType().ToString());

Для неявной типизации вместо названия типа данных используется ключевое слово var. Затем уже при компиляции компилятор сам выводит тип данных исходя из присвоенного значения. В примере выше использовалось выражение Console.WriteLine(c.GetType().ToString());, которое позволяет нам узнать выведенный тип переменной с. Так как по умолчанию все целочисленные значения рассматриваются как значения типа int, то поэтому в итоге переменная c будет иметь тип int или System.Int32

Эти переменные подобны обычным, однако они имеют некоторые ограничения.

Во-первых, мы не можем сначала объявить неявно типизируемую переменную, а затем инициализировать:

1

2

3

4

5

6

7

// этот код работает

int a;

a = 20;

 

// этот код не работает

var c;

c= 20;

Во-вторых, мы не можем указать в качестве значения неявно типизируемой переменной null:

1

2

// этот код не работает

var c=null;

Так как значение null, то компилятор не сможет вывести тип данных.

double или decimal

Из выше перечисленного списка типов данных очевидно, что если мы хотим использовать в программе числа до 256, то для их хранения мы можем использоват переменные типа byte. При использовании больших значений мы можем взять тип short, int, long. То же самое для дробных чисел - для обычных дробных чисел можно взять тип float, для очень больших дробных чисел - тип double. Тип decimal здесь стоит особняком в том плане, что несмотря на большую разрядность по сравнению с типом double, тип double может хранить большее значение. Однако значение decimal может содержать до 28 знаков после запятой, тогда как значение типа double - 15-16 знаков после запятой.

Decimal чаще находит применение в финансовых вычислениях, тогда как double - в математических операциях. Общие различия между этими двумя типами можно выразить следующей таблицей:


Decimal

Double

Наибольшее значение

~1028

~10308

Наименьшее значение (без учета нуля)

10-28

~10-323

Знаков после запятой

28

15-16

Разрядность

16 байт

8 байт

Операций в секунду

сотни миллионов

миллиарды



4