Статические классы в C#
Сегодня хотелось бы чуть подробнее остановиться на теме статических классов.
Класс считается статическим если в его сигнатуре присутствует ключевое слово
Такой класс содержит только статические члены (поля, методы, свойства и т.д.) и явно создать его экземпляр с помощью ключевого слова
Более того, на статический класс также накладываются следующие ограничения:
🔸 не может учавствовать в наследовании (служить базовым или являться наследником);
🔸 не может содержать члены с атрибутами доступа
🔸 не может иметь переопределённых (
🔸 не может содержать конструкторы экземпляров (только
Областей применения у статических классов не так много. Они служат для:
🔸 группировки вспомогательных методов (так например
🔸 определения методов расширения (extension methods).
Хочу также порекомендовать неплохую на мой взгляд русскоязычную заметку по теме - Статика в C#.
#basics
Сегодня хотелось бы чуть подробнее остановиться на теме статических классов.
Класс считается статическим если в его сигнатуре присутствует ключевое слово
static
, например:public static class Math {
// ..
}
Такой класс содержит только статические члены (поля, методы, свойства и т.д.) и явно создать его экземпляр с помощью ключевого слова
new
у нас не получится.Более того, на статический класс также накладываются следующие ограничения:
🔸 не может учавствовать в наследовании (служить базовым или являться наследником);
🔸 не может содержать члены с атрибутами доступа
protected
и protected internal
;🔸 не может иметь переопределённых (
override
) членов;🔸 не может содержать конструкторы экземпляров (только
static
);Областей применения у статических классов не так много. Они служат для:
🔸 группировки вспомогательных методов (так например
Math
агрегирует в себе математические операции, Console
содержит поля и методы для взаимодействия с консолью, Utils
как контейнер для наиболее часто используемых методов вашего приложения);🔸 определения методов расширения (extension methods).
Хочу также порекомендовать неплохую на мой взгляд русскоязычную заметку по теме - Статика в C#.
#basics
Инкремент и декремент в C#
Инкремент – это операция, которая увеличивает переменную на единицу, если переменная числовая, и возвращает следующий символ из таблицы символов, если переменная символьного типа (
Операторы инкремента записывается как два плюса:
Существуют два вида инкрементов: преинкремент (или префиксный инкремент) и постинкремент (или постфиксный инкремент). В синтаксисе префиксный инкремент ставится перед необходимой переменной, а постфиксный, соответственно, после.
Главное различие между ними, что при использовании операции преинкремента значение переменной сначала увеличивается на 1, а затем используется в выражении, к которому относится данная переменная:
А при использовании операции постинкремента значение переменной сначала используется в выражении, а потом увеличивается на 1:
Декремент – это подобная инкременту операция, с той лишь разницей, что она уменьшает числовую переменную на единицу, а для символьной переменной выбирает предшествующий ей символ из таблицы символов.
Операторы декремента записывается как два минуса:
Декремент также имеет два вида: предекремент (префиксный декремент) и постдекремент (постфиксный декремент).
Вот небольшое задание для проверки.
💬 А знаете ли вы, что синий значёк говорит нам о том, что выполнение продолжилось уже в другом потоке? 😉
#basics
Инкремент – это операция, которая увеличивает переменную на единицу, если переменная числовая, и возвращает следующий символ из таблицы символов, если переменная символьного типа (
char
).Операторы инкремента записывается как два плюса:
++
Существуют два вида инкрементов: преинкремент (или префиксный инкремент) и постинкремент (или постфиксный инкремент). В синтаксисе префиксный инкремент ставится перед необходимой переменной, а постфиксный, соответственно, после.
Главное различие между ними, что при использовании операции преинкремента значение переменной сначала увеличивается на 1, а затем используется в выражении, к которому относится данная переменная:
int n1 = 5;
int n2 = 2 * ++n1; // n2 now 12, n1 is 6
А при использовании операции постинкремента значение переменной сначала используется в выражении, а потом увеличивается на 1:
int n1 = 5;
int n2 = 2 * n1++; // n2 now 10, n1 is 6
Декремент – это подобная инкременту операция, с той лишь разницей, что она уменьшает числовую переменную на единицу, а для символьной переменной выбирает предшествующий ей символ из таблицы символов.
Операторы декремента записывается как два минуса:
--
Декремент также имеет два вида: предекремент (префиксный декремент) и постдекремент (постфиксный декремент).
int n1 = 5;
int n2 = 2 * n1--; // n2 now 10, n1 is 4
Вот небольшое задание для проверки.
💬 А знаете ли вы, что синий значёк говорит нам о том, что выполнение продолжилось уже в другом потоке? 😉
#basics
Арифметические операции в C#
Во вчерашней заметке мы рассмотрели унарные операции инкремента и декремента.
Сегодняшняя тема достаточно простая, однако, обойти её стороной, на мой взгляд, было бы неправильно. Итак.. бинарные арифметические операции в C#:
🔸 + - сложение двух чисел:
🔸 - - вычитание двух чисел:
🔸 * - умножение двух чисел:
🔸 / - деление двух чисел:
При делении стоит учитывать, что если оба операнда представляют целые числа, то результат также будет округляться до целого числа:
Хочу обратить ваше внимание на то, что несмотря на тип переменной
Для выхода из этой ситуации необходимо определять литералы или переменные, участвующие в операции, именно как типы
🔸 % - остаток от целочисленного деления:
💬 Помните ли вы порядок выполнения операторов? Вот небольшое задание для проверки 😉
#basics
Во вчерашней заметке мы рассмотрели унарные операции инкремента и декремента.
Сегодняшняя тема достаточно простая, однако, обойти её стороной, на мой взгляд, было бы неправильно. Итак.. бинарные арифметические операции в C#:
🔸 + - сложение двух чисел:
int x = 10;
int z = x + 12; // 22
🔸 - - вычитание двух чисел:
int x = 10;
int z = x - 6; // 4
🔸 * - умножение двух чисел:
int x = 10;
int z = x * 5; // 50
🔸 / - деление двух чисел:
int x = 10;
int z = x / 5; // 2
double a = 10;
double b = 3;
double c = a / b; // 3.33333333
При делении стоит учитывать, что если оба операнда представляют целые числа, то результат также будет округляться до целого числа:
double z = 10 / 4; // 2
Хочу обратить ваше внимание на то, что несмотря на тип переменной
double
, которой будет присвоено итоговое значение, результат деления будет целочисленным числом ввиду того, что литералы 10
и 4
имеют целочисленный тип int
.Для выхода из этой ситуации необходимо определять литералы или переменные, участвующие в операции, именно как типы
double
или float
:double z = 10.0 / 4.0; // 2.5
🔸 % - остаток от целочисленного деления:
double x = 10.0;
double z = x % 4.0; // 2
💬 Помните ли вы порядок выполнения операторов? Вот небольшое задание для проверки 😉
#basics
Целочисленное деление и округление в C#
При делении одного целочисленного значения на другое с помощью оператора деления
Причину этого поведения я описывал в предыдущей заметке - целочисленные аргументы приводят к целочисленному результату.
При попытке поделить на значение, равное
При попытке поделить на литерал
💬 Тем удивительнее оказывается тот факт, что в случае деления числа с плавающей точкой на ноль (
#basics
При делении одного целочисленного значения на другое с помощью оператора деления
/
результат всегда округляется до нуля. Другими словами- обрезается:int n1 = 7 / 2; // 3
long n2 = -7 / 2; // -3
short n3 = -11 / -3; // 3
Причину этого поведения я описывал в предыдущей заметке - целочисленные аргументы приводят к целочисленному результату.
При попытке поделить на значение, равное
0
, мы получим исключение System.DivideByZeroException
в runtime:int i = 0;
int r = 7 / i; // DivideByZeroException
При попытке поделить на литерал
0
мы получим исключение на этапе компиляции:int r = 7 / 0; // Division by constant zero
💬 Тем удивительнее оказывается тот факт, что в случае деления числа с плавающей точкой на ноль (
1.0 / 0
) вышеупомянутое исключение выброшено не будет. Мы просто получим в результате бесконечность (Infinity
) 🙂#basics
Округление чисел с плавающей точкой в C#
Во время разработки мы временами сталкиваемся с необходимостью округлить число с плавающей точкой типа
Поэтому в дело вступает явное приведение:
Однако, с этим кодом всё не так просто. Дело в том, что подобное округление на деле окажется ничем иным, как отбрасыванием дробной части у целочисленного значения.
Если же мы хотим руководствоваться математическими правилами округления, то с этим нам поможет класс System.Convert:
Но и здесь всё не всегда так гладко 😅 Оказывается, в .NET алгоритм округления (banker's rounding) отличается от привычного нам в тех случаях, когда значения являются пограничными: 0.5, 3.5. В этих случаях округление осуществляется в пользу ближайшего чётного:
💬 Заинтересованы алгоритмом и причиной подобного решения в .NET? Подробнее почитать об этом вы сможете уже самостоятельно здесь 😉
#basics
Во время разработки мы временами сталкиваемся с необходимостью округлить число с плавающей точкой типа
float
или double
к целочисленному значению типа int
. Сделать это неявно, как я уже упоминал ранее, у нас не получится ввиду отсутствия реализации подобного приведения:int n1 = 4.8f; // Cannot implicitly convert
Поэтому в дело вступает явное приведение:
int n1 = (int)4.8f;
Однако, с этим кодом всё не так просто. Дело в том, что подобное округление на деле окажется ничем иным, как отбрасыванием дробной части у целочисленного значения.
Если же мы хотим руководствоваться математическими правилами округления, то с этим нам поможет класс System.Convert:
float f1 = 4.8f;
int n1 = Convert.ToInt32(4.8f); // 5
Но и здесь всё не всегда так гладко 😅 Оказывается, в .NET алгоритм округления (banker's rounding) отличается от привычного нам в тех случаях, когда значения являются пограничными: 0.5, 3.5. В этих случаях округление осуществляется в пользу ближайшего чётного:
int n1 = Convert.ToInt32(8.5f); // 8
int n2 = Convert.ToInt32(9.5f); // 10
💬 Заинтересованы алгоритмом и причиной подобного решения в .NET? Подробнее почитать об этом вы сможете уже самостоятельно здесь 😉
#basics