Булевы (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# и .NET.
Предлагаю вашему внимаю самые 🔥 интересные статьи и вопросы этой недели:
🔸 What's Coming to C#?
🔸 Keynote from the people who build .NET
🔸 C# Back to Basics – Working With Files, File and Directory
🔸 How to determine the size of var?
Всем удачных выходных 😉
#sof_weekly
Предлагаю вашему внимаю самые 🔥 интересные статьи и вопросы этой недели:
🔸 What's Coming to C#?
🔸 Keynote from the people who build .NET
🔸 C# Back to Basics – Working With Files, File and Directory
🔸 How to determine the size of var?
Всем удачных выходных 😉
#sof_weekly
Порядок выполнения операторов в 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#
В языке C# тип (например
Переменная является хранилищем данных. Каждая переменная может содержать значение конкретного типа (экземпляр), которое может меняться во время исполнения программы.
Константы являются переменными, значения которых неизменны и определены уже на этапе компиляции. Они так же хранят в себе значения (экземпляры) конкретных типов.
Выражения возвращают конкретные значения по итогу их успешного исполнения. У выражений так же есть конкретный тип.
В языке C# доступны не только большое кол-во встроенных типов (например
💬 Вот такое на первый взгляд необычное поведение связано с особенностью констант в языке C#. Если вас оно удивляет, то по ссылке вы найдёте ответ на вопрос, почему так происходит.
#data_types
В языке C# тип (например
int
) определяет каким будет значение (42
) хранящееся в переменной. Переменная является хранилищем данных. Каждая переменная может содержать значение конкретного типа (экземпляр), которое может меняться во время исполнения программы.
Константы являются переменными, значения которых неизменны и определены уже на этапе компиляции. Они так же хранят в себе значения (экземпляры) конкретных типов.
Выражения возвращают конкретные значения по итогу их успешного исполнения. У выражений так же есть конкретный тип.
В языке C# доступны не только большое кол-во встроенных типов (например
int
, float
), но и конструкции, позволяющие описывать свои собственные типы (class
, enum
, struct
).💬 Вот такое на первый взгляд необычное поведение связано с особенностью констант в языке C#. Если вас оно удивляет, то по ссылке вы найдёте ответ на вопрос, почему так происходит.
#data_types
Telegraph
static vs const
There are situations where a const and a non-const have different semantics. For example: const int y = 42; static void Main() { short x = 42; Console.WriteLine(x.Equals(y)); } prints out True, whereas: static readonly int y = 42; static void Main() { short…
Value и reference типы в языке C#
Значимые и ссылочные типы являются по праву одними из базисов языка C#, а вопрос об их отличиях, как следствие, одним из самых избитых на собеседованиях, поэтому сегодня я постараюсь ответить на него со всеми подробностями:
Значимые типы:
🔸 Унаследованы от System.ValueType (которые, в свою очередь, от System.Object)
🔸 Переменная хранит непосредственно значение, а в случае присваивания его копию
🔸 В качестве аргументов передаются по значению (копируются)
🔸 Не очищаются сборщиком мусора, не имеют деструктор и финализатор
🔸 Объявляются как структура (struct) или перечисление (enum)
🔸 Объявлены с модификатором sealed, а значит не могут выступать базовыми типами для наследников
Ссылочные типы:
🔸 Унаследованы от System.Object или иного ссылочного типа
🔸 Память под экземпляры выделяется в управляемой куче (managed heap)
🔸 Переменная хранит адрес (указатель) на участок памяти в управляемой куче, где уже хранится непосредственно значение (или null)
🔸 В качестве аргументов передаются по ссылке (указатель)
🔸 Очищаются сборщиком мусора
🔸 Объявляются как класс (class), делегат (delegate) или интерфейс (interface)
🔸 Поддерживают наследование
Одной из лучших и наиболее ёмких, на мой взгляд, статей по этой теме является Memory in .NET - what goes where от Jon Skeet'а.
💬 Я намеренно не стал приводить информацию о том, что значимые типы хранятся в стеке (потока выполнения). Дело в том, что это не совсем так. Подробнее про детали реализации value type и механизм выделения памяти для значений можно почитать в статье Eric Lipert'а: The Truth About Value Types.
✅ Понравилась заметка? Так поделись и с другими 😉
#data_types
Значимые и ссылочные типы являются по праву одними из базисов языка C#, а вопрос об их отличиях, как следствие, одним из самых избитых на собеседованиях, поэтому сегодня я постараюсь ответить на него со всеми подробностями:
Значимые типы:
🔸 Унаследованы от System.ValueType (которые, в свою очередь, от System.Object)
🔸 Переменная хранит непосредственно значение, а в случае присваивания его копию
🔸 В качестве аргументов передаются по значению (копируются)
🔸 Не очищаются сборщиком мусора, не имеют деструктор и финализатор
🔸 Объявляются как структура (struct) или перечисление (enum)
🔸 Объявлены с модификатором sealed, а значит не могут выступать базовыми типами для наследников
Ссылочные типы:
🔸 Унаследованы от System.Object или иного ссылочного типа
🔸 Память под экземпляры выделяется в управляемой куче (managed heap)
🔸 Переменная хранит адрес (указатель) на участок памяти в управляемой куче, где уже хранится непосредственно значение (или null)
🔸 В качестве аргументов передаются по ссылке (указатель)
🔸 Очищаются сборщиком мусора
🔸 Объявляются как класс (class), делегат (delegate) или интерфейс (interface)
🔸 Поддерживают наследование
Одной из лучших и наиболее ёмких, на мой взгляд, статей по этой теме является Memory in .NET - what goes where от Jon Skeet'а.
💬 Я намеренно не стал приводить информацию о том, что значимые типы хранятся в стеке (потока выполнения). Дело в том, что это не совсем так. Подробнее про детали реализации value type и механизм выделения памяти для значений можно почитать в статье Eric Lipert'а: The Truth About Value Types.
✅ Понравилась заметка? Так поделись и с другими 😉
#data_types
❇️ Эта рабочая неделя оказалась весьма плодовита на интересные вопросы и статьи, которыми и спешу с вами поделиться в рамках очередной еженедельной подборки по C# и .NET.
Предлагаю вашему внимаю самые 🔥 интересные статьи и вопросы этой недели:
C#:
🔸 C# Intermediate – Properties in C#
🔸 C# 8 Small Features
🔸 Null coalescing operator IList, Array, Enumerable.Empty in foreach
🔸 C# Asynchronous with task is slower than synchronous
Debugging:
🔸 Отладка как процесс
🔸 Breakpoints FAQ: How can I pause my code in Visual Studio?
Performance:
🔸 Struct и readonly: как избежать падения производительности
🔸 Performance of value-type vs reference-type enumerators
Common:
🔸 Как мы создали технологичный продукт и провалились на дно
🔸 23 рекомендации для читабельного кода
Всем хороших и плодотворных выходных 😉
#sof_weekly
Предлагаю вашему внимаю самые 🔥 интересные статьи и вопросы этой недели:
C#:
🔸 C# Intermediate – Properties in C#
🔸 C# 8 Small Features
🔸 Null coalescing operator IList, Array, Enumerable.Empty in foreach
🔸 C# Asynchronous with task is slower than synchronous
Debugging:
🔸 Отладка как процесс
🔸 Breakpoints FAQ: How can I pause my code in Visual Studio?
Performance:
🔸 Struct и readonly: как избежать падения производительности
🔸 Performance of value-type vs reference-type enumerators
Common:
🔸 Как мы создали технологичный продукт и провалились на дно
🔸 23 рекомендации для читабельного кода
Всем хороших и плодотворных выходных 😉
#sof_weekly
Встроенные типы и C# keywords
Язык C# включает в себя большой набор встроенных (примитивных) типов, которые мы можем использовать при разработке наших программ.
Каждый их них имеет своё ключевое слово (keyword), которое соответствует встроенному типу платформы .NET. Другими словами, keyword является лишь сокращением или синонимом (alias) для конкретного типа (реализация которого находится в библиотеке BCL - base class library).
Далее представлены все доступные нам встроенные типы в формате C# тип - .NET тип - границы значений:
🔸 bool – System.Boolean – 1 byte (true|false)
🔸 byte – System.Byte – 1 byte (0 to 255)
🔸 sbyte – System.SByte – 1 byte (-128 to 127)
🔸 short – System.Int16 – 2 bytes (-32,768 to 32,767)
🔸 ushort – System.UInt16 – 2 bytes (0 to 65,535)
🔸 int – System.Int32 – 4 bytes (-2,147,483,648 to 2,147,483,647)
🔸 uint – System.UInt32 – 4 bytes (0 to 4,294,967,295)
🔸 long – System.Int64 – 8 bytes (-9,223,372,036,854,775,808 to 9,223,372,036,854,775,807)
🔸 ulong – System.UInt64 – 8 bytes (0 to 18,446,744,073,709,551,615)
🔸 float – System.Single – 4 bytes (±1.5e−45 to ±3.4e38, 7 digit precision)
🔸 double – System.Double – 8 bytes (±5.0e−324 to ±1.7e308, 15-16 digit precision)
🔸 decimal – System.Decimal – 16 bytes (±1.0 × 10−28 to ±7.9 × 1028, 28-29 digit precision)
🔸 char – System.Char – 2 bytes (U+0000 to U+ffff, UTF16 Unicode character)
🔸 object - System.Object
Подробнее: Built-in types table - C# Reference.
#data_types
Язык C# включает в себя большой набор встроенных (примитивных) типов, которые мы можем использовать при разработке наших программ.
Каждый их них имеет своё ключевое слово (keyword), которое соответствует встроенному типу платформы .NET. Другими словами, keyword является лишь сокращением или синонимом (alias) для конкретного типа (реализация которого находится в библиотеке BCL - base class library).
Далее представлены все доступные нам встроенные типы в формате C# тип - .NET тип - границы значений:
🔸 bool – System.Boolean – 1 byte (true|false)
🔸 byte – System.Byte – 1 byte (0 to 255)
🔸 sbyte – System.SByte – 1 byte (-128 to 127)
🔸 short – System.Int16 – 2 bytes (-32,768 to 32,767)
🔸 ushort – System.UInt16 – 2 bytes (0 to 65,535)
🔸 int – System.Int32 – 4 bytes (-2,147,483,648 to 2,147,483,647)
🔸 uint – System.UInt32 – 4 bytes (0 to 4,294,967,295)
🔸 long – System.Int64 – 8 bytes (-9,223,372,036,854,775,808 to 9,223,372,036,854,775,807)
🔸 ulong – System.UInt64 – 8 bytes (0 to 18,446,744,073,709,551,615)
🔸 float – System.Single – 4 bytes (±1.5e−45 to ±3.4e38, 7 digit precision)
🔸 double – System.Double – 8 bytes (±5.0e−324 to ±1.7e308, 15-16 digit precision)
🔸 decimal – System.Decimal – 16 bytes (±1.0 × 10−28 to ±7.9 × 1028, 28-29 digit precision)
🔸 char – System.Char – 2 bytes (U+0000 to U+ffff, UTF16 Unicode character)
🔸 object - System.Object
Подробнее: Built-in types table - C# Reference.
#data_types
Строковый тип в C#
В дополнении к большому количеству встроенных значимых типов, таким как целочисленные или с плавающей точкой, язык C# так же предоставляет возможность использования встроенного типа для строк.
Тип string является ссылочным и в платформе .NET (или как упоминалось ранее, в библиотеке BCL) соответствует System.String.
Строки содержат последовательность Unicode (UTF16) символов, являясь эквивалентом массиву элементов типа char, а каждый символ (элемент) занимает ровно 2 байта.
Строковый тип является неизменяемым (immutable), другими словами мы не можем изменить значение строки, не пометив на удаление старое и не создав при этом новое.
Так же нам доступен индексатор (оператор обращения по индексу) [] для доступа к конкретным символам строки.
Небольшой пример работы со строками.
Подробнее про строковый тип: Strings in C# and .NET.
💬 Если факт неизменяемости строк довольно известен, то причины этого порой не так очевидны. Исчерпывающий на мой взгляд ответ по этой теме вы сможете найти по следующей ссылке.
#data_types
В дополнении к большому количеству встроенных значимых типов, таким как целочисленные или с плавающей точкой, язык C# так же предоставляет возможность использования встроенного типа для строк.
Тип string является ссылочным и в платформе .NET (или как упоминалось ранее, в библиотеке BCL) соответствует System.String.
Строки содержат последовательность Unicode (UTF16) символов, являясь эквивалентом массиву элементов типа char, а каждый символ (элемент) занимает ровно 2 байта.
Строковый тип является неизменяемым (immutable), другими словами мы не можем изменить значение строки, не пометив на удаление старое и не создав при этом новое.
Так же нам доступен индексатор (оператор обращения по индексу) [] для доступа к конкретным символам строки.
Небольшой пример работы со строками.
Подробнее про строковый тип: Strings in C# and .NET.
💬 Если факт неизменяемости строк довольно известен, то причины этого порой не так очевидны. Исчерпывающий на мой взгляд ответ по этой теме вы сможете найти по следующей ссылке.
#data_types
Тип object в C#
Все типы платформы .NET являются наследниками System.Object, синонимом которого в языке C# является ключевое слово object.
System.Object является базовым не только для встроенных типов, но и тех, которые мы определяем самостоятельно, а значит экземпляр любого типа может быть приведён к object:
Любой класс который мы определяем в C# также автоматически является наследником от object.
Тип object определяет следующий набор доступных для использования экземплярных методов:
🔸 bool Equals(object)
🔸 void Finalize()
🔸 int GetHashCode()
🔸 Type GetType()
🔸 object MemberwiseClone()
🔸 string ToString()
Статические методы включают в себя:
🔸 bool Equals(object, object)
🔸 bool ReferenceEquals(object, object)
Другими словами, каждый из приведённых выше методов унаследован и автоматически доступен при разработке.
💬 Знаете ли вы, что в 64-битных платформах Garbage Collector не позволяет выделять объекты, размер которых превышает 2 GB и выбрасывает OutOfMemoryException? Помочь с этим нам может специальный элемент конфигурации: gcAllowVeryLargeObjects.
#data_types
Все типы платформы .NET являются наследниками System.Object, синонимом которого в языке C# является ключевое слово object.
System.Object является базовым не только для встроенных типов, но и тех, которые мы определяем самостоятельно, а значит экземпляр любого типа может быть приведён к object:
string msg = "A string";
int n = 42;
Person me = new Person("John", 33);
// Can assign anything to an object variable
object o = msg;
o = n;
o = me;
Любой класс который мы определяем в C# также автоматически является наследником от object.
Тип object определяет следующий набор доступных для использования экземплярных методов:
🔸 bool Equals(object)
🔸 void Finalize()
🔸 int GetHashCode()
🔸 Type GetType()
🔸 object MemberwiseClone()
🔸 string ToString()
Статические методы включают в себя:
🔸 bool Equals(object, object)
🔸 bool ReferenceEquals(object, object)
Другими словами, каждый из приведённых выше методов унаследован и автоматически доступен при разработке.
💬 Знаете ли вы, что в 64-битных платформах Garbage Collector не позволяет выделять объекты, размер которых превышает 2 GB и выбрасывает OutOfMemoryException? Помочь с этим нам может специальный элемент конфигурации: gcAllowVeryLargeObjects.
#data_types
Конструкторы по умолчанию у значимых типов в C#
Все значимые (value) типы, встроенные в .NET, поддерживают конструкторы по умолчанию (другими словами, конструкторы без параметров) и могут быть проинициализированы с помощью ключевого слова new. Таким образом, мы можем инициализировать экземпляры значимых типов default'ными для них значениями.
Обычно мы объявляем переменные и сразу же инициализируем их с помощью литералов, однако, ничто не мешает использовать не только new, но и ключевое слово default:
🔸 bool type = false
🔸 Numeric types (e.g. int, float) = 0 or 0.0
🔸 char type = single empty character
🔸 DateTime type = 1/1/0001 12:00:00 AM
🔸 string - не значимый тип 😉
На основании замечательной статьи от Jon Skeet - Value types and parameterless constructors стоит также отметить, что:
Операции, которые вызывают parameterless конструктор:
🔸 Использование new int();
🔸 Activator.CreateInstance (обе версии);
Операции, которые не вызывают parameterless конструктор:
🔸 Объявление переменной (неважно какой: локальной, статической, поля);
🔸 Упаковка (boxing);
🔸 Инициализация массива;
🔸 Использование default(T) и new(T) в generic методах;
Больше информации вы сможете найти в уже упомянутой выше статье и по данной ссылке.
#data_types
Все значимые (value) типы, встроенные в .NET, поддерживают конструкторы по умолчанию (другими словами, конструкторы без параметров) и могут быть проинициализированы с помощью ключевого слова new. Таким образом, мы можем инициализировать экземпляры значимых типов default'ными для них значениями.
Обычно мы объявляем переменные и сразу же инициализируем их с помощью литералов, однако, ничто не мешает использовать не только new, но и ключевое слово default:
int i;Далее представлены default значения встроенных типов:
int n1 = 12;
int n2 = new int();
int n3 = default(int);
🔸 bool type = false
🔸 Numeric types (e.g. int, float) = 0 or 0.0
🔸 char type = single empty character
🔸 DateTime type = 1/1/0001 12:00:00 AM
🔸 string - не значимый тип 😉
На основании замечательной статьи от Jon Skeet - Value types and parameterless constructors стоит также отметить, что:
Операции, которые вызывают parameterless конструктор:
🔸 Использование new int();
🔸 Activator.CreateInstance (обе версии);
Операции, которые не вызывают parameterless конструктор:
🔸 Объявление переменной (неважно какой: локальной, статической, поля);
🔸 Упаковка (boxing);
🔸 Инициализация массива;
🔸 Использование default(T) и new(T) в generic методах;
Больше информации вы сможете найти в уже упомянутой выше статье и по данной ссылке.
#data_types
❇️ На этой неделе компания Microsoft на конференции MSIgnite представила новый портал для обучения: Microsoft Learn.
Ну а я, по традиции, предлагаю вам ознакомиться с самыми 🔥 интересными статьями и вопросами этой недели:
C#:
🔸 C# Intermediate – Static Members, Constants and Extension Methods
🔸 C# Intermediate – Anonymous and Nullable Types
🔸 What is the difference between double? and int? for .Equals comparisons?
🔸 Check List<T> for duplications with optional words to exclude
dotNET:
🔸 Here's what's new and coming to .NET Core with versions 2.1, 2.2, and 3.0
🔸 Just-In-Time (JIT) compilation
🔸 .NET API documentation moved from MSDN to docs.microsoft.com
🔸 Деревья выражений в enterprise-разработке
Common:
🔸 Манифест Чистого Программиста или краткий конспект книги «Чистый Код» Роберта Мартина
Всем хороших и плодотворных выходных 😉
#sof_weekly
Ну а я, по традиции, предлагаю вам ознакомиться с самыми 🔥 интересными статьями и вопросами этой недели:
C#:
🔸 C# Intermediate – Static Members, Constants and Extension Methods
🔸 C# Intermediate – Anonymous and Nullable Types
🔸 What is the difference between double? and int? for .Equals comparisons?
🔸 Check List<T> for duplications with optional words to exclude
dotNET:
🔸 Here's what's new and coming to .NET Core with versions 2.1, 2.2, and 3.0
🔸 Just-In-Time (JIT) compilation
🔸 .NET API documentation moved from MSDN to docs.microsoft.com
🔸 Деревья выражений в enterprise-разработке
Common:
🔸 Манифест Чистого Программиста или краткий конспект книги «Чистый Код» Роберта Мартина
Всем хороших и плодотворных выходных 😉
#sof_weekly
Иерархия типов в C#
Все типы в .NET являются наследниками тех или иных базовых типов (за исключением System.Object, который находится на вершине иерархии).
Наследование является одним из фундаментальных атрибутов объектно-ориентированного программирования. Оно позволяет определить дочерний класс, который использует (наследует), расширяет или изменяет возможности родительского класса. Класс, члены которого наследуются, называется базовым классом. Класс, который наследует члены базового класса, называется производным классом.
C# и .NET поддерживают только одиночное наследование. Это означает, что каждый класс может наследовать члены только одного класса. Но зато поддерживается транзитивное наследование, которое позволяет определить иерархию наследования для набора типов. Другими словами, тип D может наследовать возможности типа C, который в свою очередь наследует от типа B, который наследует от базового класса A. Благодаря транзитивности наследования члены типа A будут доступны для типа D.
Больше информации и примеров вы сможете найти в следующей статье - Наследование в C# и .NET.
#data_types
Все типы в .NET являются наследниками тех или иных базовых типов (за исключением System.Object, который находится на вершине иерархии).
Наследование является одним из фундаментальных атрибутов объектно-ориентированного программирования. Оно позволяет определить дочерний класс, который использует (наследует), расширяет или изменяет возможности родительского класса. Класс, члены которого наследуются, называется базовым классом. Класс, который наследует члены базового класса, называется производным классом.
C# и .NET поддерживают только одиночное наследование. Это означает, что каждый класс может наследовать члены только одного класса. Но зато поддерживается транзитивное наследование, которое позволяет определить иерархию наследования для набора типов. Другими словами, тип D может наследовать возможности типа C, который в свою очередь наследует от типа B, который наследует от базового класса A. Благодаря транзитивности наследования члены типа A будут доступны для типа D.
Больше информации и примеров вы сможете найти в следующей статье - Наследование в C# и .NET.
#data_types
MinValue и MaxValue числовых типов в C#
Ранее мы уже рассматривали встроенные числовые типы. Сегодня хотелось бы рассказать о двух примечательных полях (константах), которые содержит каждый из них- MaxValue и MinValue. Обращаться к ним можно следующим образом:
Для чего они могут нам понадобиться?
В первую очередь, их наличие обусловлено удобством в отсутствии необходимости не только запоминать минимальные и максимальные значения разных типов, но и явно прописывать их в коде. Одно дело, когда мы используем неизменяемые константы, в которых можем быть уверены и совершенно другое, когда эти значения мы пишем сами (защита от ошибок при вводе или случайного изменения).
Во-вторых, это удобно при поиске минимальных и максимальных значений в коллекции. В случае поиска минимального элемента в массиве мы можем проинициализировать переменную, которая будет содержать результат поиска максимальным значением её типа. И уже отталкиваться от него в сравнениях как в следующем примере.
☝️ Насколько мне известно, прироста производительности от использования типов меньшего размера в циклах в C# замечено не было. Однако, при описании структур данных стоит помнить о том, что такие типы как ushort, short и byte умещаются в меньшее количество бит, а значит более предпочтительны с точки зрения performance и потребления памяти (hold on for a second, это не призыв к действию, а всего лишь напоминание 🙂).
В заключение
💬 Ну и напоследок стоит также отметить, что использовать минимальные и максимальные значения в циклах стоит с осторожностью, иначе это может привести к неожиданным последствиям. Примером тому служит следующий код (кстати говоря, это реальный вопрос с одного из собеседований). Вопрос: что выведется на экране? Ответ вы сможете найти ниже на странице 😉
#data_types
Ранее мы уже рассматривали встроенные числовые типы. Сегодня хотелось бы рассказать о двух примечательных полях (константах), которые содержит каждый из них- MaxValue и MinValue. Обращаться к ним можно следующим образом:
byte bMin = byte.MinValue;
// 0
byte bMax = byte.MaxValue;
// 255 (2^8)
char cMin = char.MinValue;
// 0x0000
char cMax = char.MaxValue;
// 0xffff (2^16)
int nMin = int.MinValue;
// -2147483648
int nMax = int.MaxValue;
// 2147483647 (2^32)
long lMin = long.MinValue;
// -9,223,372,036,854,775,808
long lMax = long.MaxValue;
// 9,223,372,036,854,775,807 (2^64)
Для чего они могут нам понадобиться?
В первую очередь, их наличие обусловлено удобством в отсутствии необходимости не только запоминать минимальные и максимальные значения разных типов, но и явно прописывать их в коде. Одно дело, когда мы используем неизменяемые константы, в которых можем быть уверены и совершенно другое, когда эти значения мы пишем сами (защита от ошибок при вводе или случайного изменения).
Во-вторых, это удобно при поиске минимальных и максимальных значений в коллекции. В случае поиска минимального элемента в массиве мы можем проинициализировать переменную, которая будет содержать результат поиска максимальным значением её типа. И уже отталкиваться от него в сравнениях как в следующем примере.
☝️ Насколько мне известно, прироста производительности от использования типов меньшего размера в циклах в C# замечено не было. Однако, при описании структур данных стоит помнить о том, что такие типы как ushort, short и byte умещаются в меньшее количество бит, а значит более предпочтительны с точки зрения performance и потребления памяти (hold on for a second, это не призыв к действию, а всего лишь напоминание 🙂).
В заключение
💬 Ну и напоследок стоит также отметить, что использовать минимальные и максимальные значения в циклах стоит с осторожностью, иначе это может привести к неожиданным последствиям. Примером тому служит следующий код (кстати говоря, это реальный вопрос с одного из собеседований). Вопрос: что выведется на экране? Ответ вы сможете найти ниже на странице 😉
#data_types
TrueString и FalseString в C#
В продолжении темы о доступных полях встроенных типов сегодня хочу рассказать о
Эти поля возвращают "True" и "False" независимо от текущих настроек региона, языка или языка программирования (C# или VB .NET). Аналогичный результат можно получить вызывая метод
Не могу вспомнить примера, когда бы они действительно могли мне пригодиться, однако, могу предположить, что это очередные фиксированные значения, которые могут быть использованы в приложении в качестве неизменяемых контрактов (например, при единообразной работе с базой данных на чтение и запись).
💬 Оказалось, что довольно большое количество разработчиков (больше 90000 просмотров) интересует вопрос: почему
#data_types
В продолжении темы о доступных полях встроенных типов сегодня хочу рассказать о
Boolean.TrueString
и Boolean.FalseString
. Эти поля дают возможность использовать строковое представление соответствующих булевых значений в коде.string trueText = bool.TrueString; // "True"
string falseText = bool.FalseString; // "False"
Эти поля возвращают "True" и "False" независимо от текущих настроек региона, языка или языка программирования (C# или VB .NET). Аналогичный результат можно получить вызывая метод
.ToString()
на соответствующем значении:bool b1 = true;
bool b2 = false;
string true2 = b1.ToString(); // "True"
string false2 = b2.ToString(); // "False"
Не могу вспомнить примера, когда бы они действительно могли мне пригодиться, однако, могу предположить, что это очередные фиксированные значения, которые могут быть использованы в приложении в качестве неизменяемых контрактов (например, при единообразной работе с базой данных на чтение и запись).
💬 Оказалось, что довольно большое количество разработчиков (больше 90000 просмотров) интересует вопрос: почему
Boolean.ToString
возвращает "True" а не "true". Причины, на удивление, есть и их несколько. О них вы сможете прочитать уже самостоятельно 😉#data_types
Создаём объекты с помощью new в C#
Для создания объекта некого типа нам необходимо создать экземпляр этого типа. В случае со значимыми типами нам достаточно присвоить им значение. Для ссылочных же потребуется использовать оператор
Принцип его работы достаточно прост:
🔸 Выделяет память под экземпляр типа и инициализирует все поля объекта значениями по умолчанию;
🔸 Вызывает конструктор типа
🔸 Возвращает ссылку на созданный объект в случае если тип ссылочный либо значение, если тип значимый
Что касается конструкторов, то их у типа может быть несколько и различаться они будут входными аргументами (конструктор не имеющий принимающий аргументов является конструктором по умолчанию). Оператор
Также стоит напомнить, что объявленные переменные ссылочных типов будут содержать значение
Больше информации и примеров вы сможете найти в следующей статье - new operator.
#data_types
Для создания объекта некого типа нам необходимо создать экземпляр этого типа. В случае со значимыми типами нам достаточно присвоить им значение. Для ссылочных же потребуется использовать оператор
new
.Принцип его работы достаточно прост:
🔸 Выделяет память под экземпляр типа и инициализирует все поля объекта значениями по умолчанию;
🔸 Вызывает конструктор типа
🔸 Возвращает ссылку на созданный объект в случае если тип ссылочный либо значение, если тип значимый
Что касается конструкторов, то их у типа может быть несколько и различаться они будут входными аргументами (конструктор не имеющий принимающий аргументов является конструктором по умолчанию). Оператор
new
оставляет за нами право выбора оного.Также стоит напомнить, что объявленные переменные ссылочных типов будут содержать значение
null
до тех пор, пока не будут проинициализированы:// Not instantiated, value is null
Person p1;
// p2 points to new instance of the Person class
// Default constructor, takes no parameters
Person p2 = new Person();
// Construct another Person object using a different constructor,
// which takes Name and Age
Person p3 = new Person("John", 42);
Больше информации и примеров вы сможете найти в следующей статье - new operator.
#data_types
❇️ Выходные на пороге, а значит время очередного еженедельного дайджеста.
Предлагаю вашему внимаю самые 🔥 интересные вопросы этой недели:
🔸 C# Intermediate – Enumerations in C#
🔸 Подводные камни HttpClient в .NET
🔸 Pattern matching в C# 7
🔸 Why does a 'for' loop behave differently when migrating VB.NET code to C#?
🔸 A History of .NET Runtimes
🔸 The danger of TaskCompletionSource<T> class
🔸 Profiling .NET Code with BenchmarkDotNet
🔸 .NET JIT compiler volatile optimizations
🔸 Встреча .Net сообщества на CLRium #4 + онлайн
Всем отличных выходных 😉
#sof_weekly
Предлагаю вашему внимаю самые 🔥 интересные вопросы этой недели:
🔸 C# Intermediate – Enumerations in C#
🔸 Подводные камни HttpClient в .NET
🔸 Pattern matching в C# 7
🔸 Why does a 'for' loop behave differently when migrating VB.NET code to C#?
🔸 A History of .NET Runtimes
🔸 The danger of TaskCompletionSource<T> class
🔸 Profiling .NET Code with BenchmarkDotNet
🔸 .NET JIT compiler volatile optimizations
🔸 Встреча .Net сообщества на CLRium #4 + онлайн
Всем отличных выходных 😉
#sof_weekly
Создание объектов и куча (Heap) в C#
В прошлый раз мы рассмотрели оператор
Объекты .NET размещаются в области памяти, которая называется управляемой кучей (managed heap), откуда они автоматически удаляются сборщиком мусора, когда наступает "определенный момент в будущем" 🙂. Куча представляет собой непрерывную область памяти, поделённую на занятые и свободные области (блоки) различного размера.
При программировании на языке C# мы можем смело полагать, что исполняющая среда .NET будет сама заботиться об управляемой куче без непосредственного нашего с вами вмешательства.
После создания объект будет автоматически удален сборщиком мусора тогда, когда в нем отпадет необходимость. Разумеется, возникает вопрос о том, каким образом сборщик мусора определяет момент, когда в объекте отпадает необходимость? В двух словах на этот вопрос можно ответить так: сборщик мусора удаляет объект из кучи тогда, когда тот становится недостижимым ни в одной части программного кода.
Возвращаясь к примеру, который я уже скидывал ранее теперь мы можем лучше понимать, что происходит в следующей строке:
Оператор
Больше деталей вы сможете найти по ссылке - автоматическое управление памятью.
#data_types
В прошлый раз мы рассмотрели оператор
new
и принцип его работы. Сегодня я хотел бы упомянуть о такой немаловажной детали как куча.Объекты .NET размещаются в области памяти, которая называется управляемой кучей (managed heap), откуда они автоматически удаляются сборщиком мусора, когда наступает "определенный момент в будущем" 🙂. Куча представляет собой непрерывную область памяти, поделённую на занятые и свободные области (блоки) различного размера.
При программировании на языке C# мы можем смело полагать, что исполняющая среда .NET будет сама заботиться об управляемой куче без непосредственного нашего с вами вмешательства.
После создания объект будет автоматически удален сборщиком мусора тогда, когда в нем отпадет необходимость. Разумеется, возникает вопрос о том, каким образом сборщик мусора определяет момент, когда в объекте отпадает необходимость? В двух словах на этот вопрос можно ответить так: сборщик мусора удаляет объект из кучи тогда, когда тот становится недостижимым ни в одной части программного кода.
Возвращаясь к примеру, который я уже скидывал ранее теперь мы можем лучше понимать, что происходит в следующей строке:
class1 cls1 = new class1();
Оператор
new
выделяет память под объект типа class1
и располагает его в Heap. В то же время на стеке выделяется память под переменную cls1
, которая будет хранить ссылку на создаваемый нами объект. И затем ссылка на только что созданный объект уже присваивается в нашу переменную. Вы можете также заметить, что по завершению выполнения метода Method1
его стек очищается, в то время как объект всё так же присутствует в куче, становясь, тем самым, кандидатом для очистки при следующей сборки мусора.Больше деталей вы сможете найти по ссылке - автоматическое управление памятью.
#data_types
Поведение переменных ссылочных типов в C#
Как вы уже знаете, переменные значимых типов хранят в себе непосредственно значение, в то время как переменные ссылочных типов лишь ссылку на объект. В связи с этим нам необходимо помнить о том, что при присваивании значения одной ссылочной переменной другой, обе они в итоге начинают ссылаться на один и тот же объект в куче:
Таким образом, если мы изменим значения полей объекта
Подробности вы сможете найти по ссылке - Six important .NET concepts: Stack, heap, value types, reference types, boxing, and unboxing.
#data_types
Как вы уже знаете, переменные значимых типов хранят в себе непосредственно значение, в то время как переменные ссылочных типов лишь ссылку на объект. В связи с этим нам необходимо помнить о том, что при присваивании значения одной ссылочной переменной другой, обе они в итоге начинают ссылаться на один и тот же объект в куче:
public void Method1() {
cls1 obj = new cls1();
cls1 obj1 = obj;
}
Таким образом, если мы изменим значения полей объекта
obj
, то мы увидим данные изменения и в переменной obj1
. Это подтверждает что обе переменных ссылаются на один и тот же объект.Подробности вы сможете найти по ссылке - Six important .NET concepts: Stack, heap, value types, reference types, boxing, and unboxing.
#data_types
Статические члены классов в 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