#basics
Как и зачем возвращать результат выполнения метода Main
По умолчанию точка входа в наше приложение - метод Main объявлен с типом возвращаемого значения void. Однако, мы так же имеем возможность возвращать и целочисленное значение int (а начиная с C# 7.1 ещё и Task<int>):
Стоит заметить, что сделать это получится лишь в том случае, когда информация о возвращаемых значениях и способах реагирования на них будет определена заранее, как в следующем примере на powershell:
@csharp_1001_notes
Как и зачем возвращать результат выполнения метода Main
По умолчанию точка входа в наше приложение - метод Main объявлен с типом возвращаемого значения void. Однако, мы так же имеем возможность возвращать и целочисленное значение int (а начиная с C# 7.1 ещё и Task<int>):
class ProgramНужно это в первую очередь для того, чтобы код, вызывающий нашу программу, имел возможность отреагировать на результат её выполнения.
{
static int Main()
{
if (DateTime.Today.DayOfWeek == DayOfWeek.Monday)
return -1; // Monday is bad
else
return 0;
}
}
Стоит заметить, что сделать это получится лишь в том случае, когда информация о возвращаемых значениях и способах реагирования на них будет определена заранее, как в следующем примере на powershell:
dotnet run💬 А знаете ли вы, что alias void в языке C# соответствует структуре public struct Void из сборки System? 😉
if ($LastExitCode -eq 0) {
Write-Host "Execution succeeded"
} else
{
Write-Host "Execution Failed"
}
Write-Host "Return value = " $LastExitCode
@csharp_1001_notes
Может ли Main быть public?
TL;DR Может, но Microsoft не рекомендует:
В случае же наличия у него модификатора доступа
💬 Тем, кто так же как и я озадачился закономерным вопросом "А как на самом деле вызывается метод Main и что происходит до него?" я прикладываю эту ссылку на строку в CoreCLR, ответственную за его вызов 😉
#basics
TL;DR Может, но Microsoft не рекомендует:
Main must be static and it need not be public.
🔶 Почему может? Потому что язык C# и платформа .NET не накладывают никаких ограничений на модификаторы доступа для метода Main и следующий код будет успешно скомпилирован:class Program🔶 Почему не рекомендуется? Потому что предполагается, что данный метод будет вызван лишь 1 раз исполняющей средой (CLR) и является точкой входа в ваше приложение.
{
static public void Main()
{
Console.WriteLine("This would compile..");
}
}
В случае же наличия у него модификатора доступа
public
, он станет доступен для вызова из других частей вашего приложения.💬 Тем, кто так же как и я озадачился закономерным вопросом "А как на самом деле вызывается метод Main и что происходит до него?" я прикладываю эту ссылку на строку в CoreCLR, ответственную за его вызов 😉
#basics
GitHub
coreclr/src/vm/corhost.cpp at d4f533b39db726cc61b0c8a5baab0f8c01c1fe7b · dotnet/coreclr
CoreCLR is the runtime for .NET Core. It includes the garbage collector, JIT compiler, primitive data types and low-level classes. - dotnet/coreclr
Идентификаторы и правила их именования в C#
Под идентификатором (identifier) в языке C# считаются любые имена, которые мы используем в именах переменных, классов, интерфейсов, методов, свойств, пространств имён и так далее.
На именование идентификаторов накладываются следующие ограничения:
🔸 Case sensitive -
🔸 Не могут начинаться с цифр;
🔸 Не могут содержать пробелы;
🔸 Могут включать в себя Unicode символы:
🔸 Не могут совпадать с ключевыми словами (keywords) языка;
Что касается последнего правила, то обойти его можно используя символ
#basics
Под идентификатором (identifier) в языке C# считаются любые имена, которые мы используем в именах переменных, классов, интерфейсов, методов, свойств, пространств имён и так далее.
На именование идентификаторов накладываются следующие ограничения:
🔸 Case sensitive -
name
!= Name
;🔸 Не могут начинаться с цифр;
🔸 Не могут содержать пробелы;
🔸 Могут включать в себя Unicode символы:
string имя = "";
и class 国家 { }
вполне себе валидные идентификаторы, но делать так без необходимости противопоказано ⛔️ То же относится и к именованию файлов в вашем проекте;🔸 Не могут совпадать с ключевыми словами (keywords) языка;
Что касается последнего правила, то обойти его можно используя символ
@
в качестве префикса в имени идентификатора, однако, без веских на то причин, я вам так же порекомендую этого не делать:class @class
{
int @int;
string @default;
}
#basics
Контекстные (Contextual) ключевые слова C#
Язык C# включает в себя перечень ключевых слов (keywords), использование которых определяется контекстом выполнения. Говоря проще, когда они находятся в нужном месте, они выполняют определённую для них функцию:
В противном случае- они ничем не отличаются от обычных идентификаторов.
Вот их неполный список:
Более того, они не являются зарезервированными, а значит их можно (но так же не рекомендуется ⛔️) использовать в качестве имён без специального символа
Стоит заметить, что кроме contextual keywords так же в языке существуют следующие группы ключевых слов:
🔸 Statement keywords;
🔸 Operator keywords;
🔸 Conversion keywords;
🔸 Access keywords;
🔸 Literal keywords;
🔸 Query keywords;
Количество ключевых слов продолжает рости по мере развития языка и на сегодняшний день оно составляет уже 78 штук.
✅ Понравилась заметка? Тогда поделись ей с другими 😉
#basics
Язык C# включает в себя перечень ключевых слов (keywords), использование которых определяется контекстом выполнения. Говоря проще, когда они находятся в нужном месте, они выполняют определённую для них функцию:
var x = "y";
dynamic m = "n";
string t = nameof(x);
В противном случае- они ничем не отличаются от обычных идентификаторов.
Вот их неполный список:
async
, dynamic
, global
, join
, value
, await
, select
, var
, get
, nameof
, set
и другие.Более того, они не являются зарезервированными, а значит их можно (но так же не рекомендуется ⛔️) использовать в качестве имён без специального символа
@
следующим образом:var var = "";
bool async = false;
string dynamic = "";
int get = 1;
Стоит заметить, что кроме contextual keywords так же в языке существуют следующие группы ключевых слов:
🔸 Statement keywords;
🔸 Operator keywords;
🔸 Conversion keywords;
🔸 Access keywords;
🔸 Literal keywords;
🔸 Query keywords;
Количество ключевых слов продолжает рости по мере развития языка и на сегодняшний день оно составляет уже 78 штук.
✅ Понравилась заметка? Тогда поделись ей с другими 😉
#basics
Docs
C# Keywords and contextual keywords - C# reference
C# Keywords: Find the reference material for the predefined keywords and contextual keywords defined in the C# language.
Что такое литералы (Literals) ключевые слова C#
Литерал - это способ представления значения в исходном коде. Чаще всего мы используем их при инициализации переменных и констант, передаче в качестве аргументов в вызовы методов, форматировании и проверке значений на равенство.
🔸 Boolean - true / false;
🔸 Integer - 12, 24L, 100UL, 0x7DC;
🔸 Floating-point - 1.0, 2.2F, 6.02E23, 123.45m;
🔸 Character - 'b', 'Y', '!', '\n', '\x04DA';
🔸 String - "C#", "Look Ӛ", "Line 1\nLine 2";
🔸 Null - null;
Начиная с C# 7.0 в нашем распоряжении так же появился не только новый вид литерала:
🔸 Binary - 0b00001111, 0b1111000011110000;
Но и весьма удобный с точки зрения читаемости способ их записи посредством разделения с помощью
Чуть более подробно можно почитать в этой замечательной статье.
💬 А знаете ли вы, что кроме стандартного объявления индексатора:
Мы можем также использовать
Ни разу не пригодилось, но крайне любопытно 😉
#basics
Литерал - это способ представления значения в исходном коде. Чаще всего мы используем их при инициализации переменных и констант, передаче в качестве аргументов в вызовы методов, форматировании и проверке значений на равенство.
🔸 Boolean - true / false;
🔸 Integer - 12, 24L, 100UL, 0x7DC;
🔸 Floating-point - 1.0, 2.2F, 6.02E23, 123.45m;
🔸 Character - 'b', 'Y', '!', '\n', '\x04DA';
🔸 String - "C#", "Look Ӛ", "Line 1\nLine 2";
🔸 Null - null;
Начиная с C# 7.0 в нашем распоряжении так же появился не только новый вид литерала:
🔸 Binary - 0b00001111, 0b1111000011110000;
Но и весьма удобный с точки зрения читаемости способ их записи посредством разделения с помощью
_
:ushort s1 = 0b1011_1100_1011_0011;
int x1 = 0x44aa_abcd;
Чуть более подробно можно почитать в этой замечательной статье.
💬 А знаете ли вы, что кроме стандартного объявления индексатора:
public string this[string key] {
get { return internalDictionary[key]; }
}
// Usage: something["x"]
Мы можем также использовать
params
:public string this[params string[] keys] {
get { return internalDictionary[key]; }
}
// Usage: something["x", "y", "z"]
Ни разу не пригодилось, но крайне любопытно 😉
#basics
Булевы (Boolean) литералы в C#
Булевы литералы или, говоря проще, логические значения "Истина" (да) и "Ложь" (нет) представлены ключевыми словами true и false.
В исходном коде чаще всего используется ключевое слово bool, являющееся на деле alias для структуры System.Boolean:
Значением по умолчанию является false.
💬 Задумывались ли вы, почему в языке C# тип System.Boolean занимает 1 байт? Ведь для кодирования значений 0 и 1 достаточно всего лишь одного бита.
Если вам интересно, почему же так происходит, то по этой ссылке вы узнаете ответ 😉
#basics
Булевы литералы или, говоря проще, логические значения "Истина" (да) и "Ложь" (нет) представлены ключевыми словами true и false.
В исходном коде чаще всего используется ключевое слово bool, являющееся на деле alias для структуры System.Boolean:
bool isValid = true;
bool hasErrors = false;
Значением по умолчанию является false.
💬 Задумывались ли вы, почему в языке C# тип System.Boolean занимает 1 байт? Ведь для кодирования значений 0 и 1 достаточно всего лишь одного бита.
Если вам интересно, почему же так происходит, то по этой ссылке вы узнаете ответ 😉
#basics
Выражения, операторы и операнды в C#
Ранее мы уже рассматривали литералы и типы данных. Сегодня предлагаю определить такие понятия как выражения, операторы и операнды.
Чаще всего выражение состоит из оператора, операндов и присваивания результата выполнения и выглядит следующим образом:
В данном примере "+" является оператором сложения, который применяется к двум операндам (1 и 2), результат выполнения которого присваивается оператором "=" переменной типа int.
Разумеется, в качестве операндов могут выступать не только литералы, но и переменные, константы, результаты выполнения других операторов или методов и так далее.
Говоря про оператор присваивания можно заметить, что он достаточно прост и принимает два операнда. Left hand операнд является переменной, которой будет присвоен right hand операнд.
Операторы присваивания и сложения это далеко не все доступные операторы. На данный момент их количество в языке C# составляет уже более 42 штук.
💯 Дорогие подписчики, сегодня, в 256 день в году, поздравляю всех вас с днём программиста 🍰 А наш канал, со своей первой важной отметкой в 100 читателей. Спасибо что вы с нами!
#basics
Ранее мы уже рассматривали литералы и типы данных. Сегодня предлагаю определить такие понятия как выражения, операторы и операнды.
Чаще всего выражение состоит из оператора, операндов и присваивания результата выполнения и выглядит следующим образом:
int result = 1 + 2;
В данном примере "+" является оператором сложения, который применяется к двум операндам (1 и 2), результат выполнения которого присваивается оператором "=" переменной типа int.
Разумеется, в качестве операндов могут выступать не только литералы, но и переменные, константы, результаты выполнения других операторов или методов и так далее.
Говоря про оператор присваивания можно заметить, что он достаточно прост и принимает два операнда. Left hand операнд является переменной, которой будет присвоен right hand операнд.
x = 10;
// = - operator
// x - left hand operand
// 10 - right hand operand
x = y + z;
// = - operator
// x - left hand operand
// (y + z) - right hand operand
// + - operator
// y - left hand operand
// z - right hand operand
Операторы присваивания и сложения это далеко не все доступные операторы. На данный момент их количество в языке C# составляет уже более 42 штук.
💯 Дорогие подписчики, сегодня, в 256 день в году, поздравляю всех вас с днём программиста 🍰 А наш канал, со своей первой важной отметкой в 100 читателей. Спасибо что вы с нами!
#basics
Порядок выполнения операторов в C#
Каждый оператор в языке C# характеризуется приоритетом, в котором он будет выполнен при исполнении выражения.
В том случае, когда выражение содержит операторы, приоритет выполнения которых одинаковый, то исполнение осуществляется слева направо, за исключением операторов присваивания и сравнения (у них порядок справа налево).
Далее представлены группы операторов, отсортированные по приоритету (в рамках группы приоритет одинаковый):
Стоит так же заметить, что порядок выполнения операторов в выражении может быть изменён путём добавления круглых скобок (в таком случае по аналогии с математическими выражениями, приоритет исполнения заключённых операторов будет выше).
#basics
Каждый оператор в языке C# характеризуется приоритетом, в котором он будет выполнен при исполнении выражения.
В том случае, когда выражение содержит операторы, приоритет выполнения которых одинаковый, то исполнение осуществляется слева направо, за исключением операторов присваивания и сравнения (у них порядок справа налево).
Далее представлены группы операторов, отсортированные по приоритету (в рамках группы приоритет одинаковый):
🔸 Pimary: x.y f(x) a[x] x++ x– new typeof checked unchecked
🔸 Unary: + – ! ~ ++x –x (T)x
🔸 Multiplicative: * / %
🔸 Additive: + –
🔸 Shift: << >>
🔸 Relational: < > <= >= is as
🔸 Equality: == !=
🔸 Logical AND: &
🔸 Logical XOR: ^
🔸 Logical OR: |
🔸 Conditional AND: &&
🔸 Conditional OR: ||
🔸 Conditional: ?:
🔸 Assignment: = *= /= %= += -= <<= >>= &= ^= |=
Стоит так же заметить, что порядок выполнения операторов в выражении может быть изменён путём добавления круглых скобок (в таком случае по аналогии с математическими выражениями, приоритет исполнения заключённых операторов будет выше).
#basics
Комментарии в C#
В исходном коде на языке C# доступна возможность оставлять комментарии, которые будут проигнорированы компилятором и не окажут никакого эффекта на итоговую программу.
Есть 2 способа это сделать:
🔸 Однострочный комментарий - начинается с двойных слешей
🔸 Многострочный комментарий - окружён с обоих сторон слешом и звёздочкой
Отдельно стоит упомянуть так же XML Comments (подробнее), которые благодаря стандартизации в дальнейшем используются не только при подсказках IntelliSense, но и являются источником данных при генерации документации на основании кода (например в Swagger):
☝️ Полезными в данном случае горячими клавишами при разработке являются Ctrl+K, Ctrl+C (закомментировать выделенное) и Ctrl+K, Ctrl+U (раскомментировать выделенное).
Подробнее по теме порекомендую почитать следующую статью: комментирование кода - хорошие, плохие и отвратительные комментарии.
#basics
В исходном коде на языке C# доступна возможность оставлять комментарии, которые будут проигнорированы компилятором и не окажут никакого эффекта на итоговую программу.
Есть 2 способа это сделать:
🔸 Однострочный комментарий - начинается с двойных слешей
// Adds two integers and returns the result
public static int Add(int a, int b) {
}
🔸 Многострочный комментарий - окружён с обоих сторон слешом и звёздочкой
/*
The main Math class
Contains all methods for performing basic math functions
*/
public class Math {
}
Отдельно стоит упомянуть так же XML Comments (подробнее), которые благодаря стандартизации в дальнейшем используются не только при подсказках IntelliSense, но и являются источником данных при генерации документации на основании кода (например в Swagger):
/// <summary>
/// This class performs an important function.
/// </summary>
public class MyClass {}
☝️ Полезными в данном случае горячими клавишами при разработке являются Ctrl+K, Ctrl+C (закомментировать выделенное) и Ctrl+K, Ctrl+U (раскомментировать выделенное).
Подробнее по теме порекомендую почитать следующую статью: комментирование кода - хорошие, плохие и отвратительные комментарии.
#basics
Статические члены классов в C#
Когда мы создаём новый объект и используем переменную ссылочного типа для вызова методов, мы используем экземплярные методы (instance members) и поля объекта, таким образом взаимодействуя с экземпляром проинициализированного ранее типа.
Тем не менее, мы также можем использовать статические методы (static members) и поля класса без непосредственного создания его экземпляра. В таком случае мы оперируем самим типом класса.
Статический класс по большей части такой же, как и нестатический, однако, имеется одно значительное отличие: экземпляры статического класса создавать нельзя. Другими словами, мы не сможем использовать ключевое слово
Далеко ходить за примерами не придётся: вспомните хотя бы классы
В дальнейшем мы ещё не раз вернёмся к этой теме, а пока что порекомендую ознакомиться со следующим разделом документации - Static Classes and Static Class Members.
💬 Когда использовать статические классы в C# - вопрос не праздный, поэтому ответ на него я вам порекомендую уже в качестве самостоятельного изучения 👨💻
#basics
Когда мы создаём новый объект и используем переменную ссылочного типа для вызова методов, мы используем экземплярные методы (instance members) и поля объекта, таким образом взаимодействуя с экземпляром проинициализированного ранее типа.
Тем не менее, мы также можем использовать статические методы (static members) и поля класса без непосредственного создания его экземпляра. В таком случае мы оперируем самим типом класса.
Статический класс по большей части такой же, как и нестатический, однако, имеется одно значительное отличие: экземпляры статического класса создавать нельзя. Другими словами, мы не сможем использовать ключевое слово
new
и переменные для хранения. Таким образом, доступ к членам статического класса осуществляется непосредственно с использованием имени его типа:double dub = -3.14;
Console.WriteLine(Math.Abs(dub));
Console.WriteLine(Math.Floor(dub));
Console.WriteLine(Math.Round(Math.Abs(dub)));
Далеко ходить за примерами не придётся: вспомните хотя бы классы
Console
или Math
😉 Мы не создаём их экземпляры каждый раз, когда хотим выполнить математическую операцию или вывести что-либо на экран консоли, достаточо лишь обратиться к ним по именам.В дальнейшем мы ещё не раз вернёмся к этой теме, а пока что порекомендую ознакомиться со следующим разделом документации - Static Classes and Static Class Members.
💬 Когда использовать статические классы в C# - вопрос не праздный, поэтому ответ на него я вам порекомендую уже в качестве самостоятельного изучения 👨💻
#basics
Статические классы в 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