День пятьдесят третий. #TipsAndTricks
Условие Прерывания на Исключении
В Visual Studio, вы можете использовать окно Exception Settings (Debug -> Windows -> Exception Settings) для управления исключениями: на каких исключениях среда должна прерываться, а также добавлять и удалять исключения. В Visual Studio 2017 появились дополнительные возможности управления. Вы можете установить условие прерывания.
Перейдите в окно Exception Settings и выберите типы исключений, для которых вы хотите задать условие. Выберите Редактировать Условие (Edit Condition). Здесь введите название модулей, в которых вы хотите, чтобы выполнение прерывалось. В настоящее время доступно только условие по имени модуля. Таким образом, при выполнении кода Visual Studio будет выбрасывать исключение CLR только при удовлетворении условию. Это полезно, когда вы хотите исключить срабатывание на известных ошибках какой-либо библиотеки (сторонней или находящейся в разработке).
Источник: https://dailydotnettips.com/
Условие Прерывания на Исключении
В Visual Studio, вы можете использовать окно Exception Settings (Debug -> Windows -> Exception Settings) для управления исключениями: на каких исключениях среда должна прерываться, а также добавлять и удалять исключения. В Visual Studio 2017 появились дополнительные возможности управления. Вы можете установить условие прерывания.
Перейдите в окно Exception Settings и выберите типы исключений, для которых вы хотите задать условие. Выберите Редактировать Условие (Edit Condition). Здесь введите название модулей, в которых вы хотите, чтобы выполнение прерывалось. В настоящее время доступно только условие по имени модуля. Таким образом, при выполнении кода Visual Studio будет выбрасывать исключение CLR только при удовлетворении условию. Это полезно, когда вы хотите исключить срабатывание на известных ошибках какой-либо библиотеки (сторонней или находящейся в разработке).
Источник: https://dailydotnettips.com/
День пятьдесят четвёртый. #ЗаметкиНаПолях
Атрибуты. Начало
Атрибуты предоставляют мощный способ связывания метаданных с кодом.
Свойства атрибутов:
- Добавление метаданных в вашу программу, то есть информации о типах, определённых в программе. Все сборки .NET содержат набор метаданных, описывающих типы и члены типов, определённые в сборке. Можно добавлять свои атрибуты, создавая классы-наследники
- Вы можете применить один или несколько атрибутов ко всей сборке, модулю или более мелким элементам программы, таким как классы и свойства.
- Атрибуты могут принимать аргументы так же, как методы и свойства.
- Ваша программа может получать доступ к своим метаданным или к метаданным других программ, используя рефлексию.
Использование атрибутов
Атрибуты могут применяться к практически любому объявлению: сборкам, модулям, типам, полям, возвращаемым значениям, методам, параметрам, свойствам, событиям, а также к полям и методам, создаваемым компилятором. Атрибуты указываются в квадратных скобках (
В этом примере атрибут
Параметры атрибутов
Многие атрибуты имеют параметры, которые могут быть позиционными (неименованными) или именованными. Позиционные параметры обязаны указываться в определённом порядке и не могут быть опущены. Именованные параметры не обязательны и могут указываться в любом порядке. Позиционные параметры указываются первыми. Следующие три атрибута эквивалентны:
Целевые объекты атрибутов
Целевой объект атрибута – это сущность, к которой применяется атрибут. По умолчанию атрибут применяется к элементу, которому он предшествует. Но вы можете явно определить, например, относится ли атрибут к методу, его параметру, либо к возвращаемому значению.
В следующем примере атрибуты применяются к сборке и модулю:
-
-
-
-
-
Атрибуты. Начало
Атрибуты предоставляют мощный способ связывания метаданных с кодом.
Свойства атрибутов:
- Добавление метаданных в вашу программу, то есть информации о типах, определённых в программе. Все сборки .NET содержат набор метаданных, описывающих типы и члены типов, определённые в сборке. Можно добавлять свои атрибуты, создавая классы-наследники
System.Attribute
.- Вы можете применить один или несколько атрибутов ко всей сборке, модулю или более мелким элементам программы, таким как классы и свойства.
- Атрибуты могут принимать аргументы так же, как методы и свойства.
- Ваша программа может получать доступ к своим метаданным или к метаданным других программ, используя рефлексию.
Использование атрибутов
Атрибуты могут применяться к практически любому объявлению: сборкам, модулям, типам, полям, возвращаемым значениям, методам, параметрам, свойствам, событиям, а также к полям и методам, создаваемым компилятором. Атрибуты указываются в квадратных скобках (
[]
) над объявлением сущности, к которой они применяются.В этом примере атрибут
SerializableAttribute
используется для объявления характеристики класса:[Serializable]По соглашению все имена атрибутов заканчиваются словом "
public class SampleClass
{
// Объекты этого типа могут быть сериализованы.
}
Attribute
", чтобы отделять их от других элементов библиотек .NET. Но его можно опускать при использовании атрибутов в коде. Например, [DllImport
] эквивалентно [DllImportAttribute
], но настоящее имя класса атрибута в библиотеке классов .NET Framework - DllImportAttribute
.Параметры атрибутов
Многие атрибуты имеют параметры, которые могут быть позиционными (неименованными) или именованными. Позиционные параметры обязаны указываться в определённом порядке и не могут быть опущены. Именованные параметры не обязательны и могут указываться в любом порядке. Позиционные параметры указываются первыми. Следующие три атрибута эквивалентны:
[DllImport("user32.dll")]Первый параметр (имя DLL) позиционный и всегда идёт первым. Другие параметры именованные, оба по умолчанию имеют значение false, поэтому могут быть опущены. Позиционные параметры – это параметры конструктора атрибута, именованные соответствуют свойствам или полям атрибута.
[DllImport("user32.dll", SetLastError=false, ExactSpelling=false)]
[DllImport("user32.dll", ExactSpelling=false, SetLastError=false)]
Целевые объекты атрибутов
Целевой объект атрибута – это сущность, к которой применяется атрибут. По умолчанию атрибут применяется к элементу, которому он предшествует. Но вы можете явно определить, например, относится ли атрибут к методу, его параметру, либо к возвращаемому значению.
В следующем примере атрибуты применяются к сборке и модулю:
using System;А в этом примере атрибуты применяются к методу и к возвращаемому значению метода:
using System.Reflection;
[assembly: AssemblyTitleAttribute("Production assembly 4")]
[module: CLSCompliant(true)]
// по умолчанию: применяется к методуЗамечание. Некоторые целевые объекты обязательны для указания в атрибуте для разрешения конфликтов между неоднозначными целевыми объектами атрибута:
[ValidatedContract]
int Method1() { return 0; }
// применяется к методу
[method: ValidatedContract]
int Method2() { return 0; }
// применяется к возвращаемому значению
[return: ValidatedContract]
int Method3() { return 0; }
-
assembly
– сборка,-
module
– модуль,-
return
– возвращаемое значение,-
field
(для полей, созданных компилятором),-
method
(для методов, созданных компилятором).Примеры использования атрибутов
Далее приведены несколько наиболее частых примеров использования атрибутов в коде:
- Атрибутом
- Описание маршалинга параметров метода при взаимодействии с машинным кодом.
- Описание свойств COM для классов, методов и интерфейсов.
- Вызов неуправляемого кода с помощью атрибута
- Описание названия, версии, описания или торговой марки вашей сборки.
- Описание сериализуемых членов класса.
- Описание соответствия членов класса узлам XML при XML-сериализации.
- Описание требований безопасности для методов.
- Управление оптимизацией JIT-компилятора.
- Получение информации об объекте, вызвавшем метод.
Источники:
- Джеффри Рихтер “CLR via C#”. 3-е изд. – СПб.: Питер, 2012. Глава 18.
- https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/attributes/
Далее приведены несколько наиболее частых примеров использования атрибутов в коде:
- Атрибутом
WebMethod
в веб-сервисах помечаются методы, которые можно вызывать по протоколу SOAP.- Описание маршалинга параметров метода при взаимодействии с машинным кодом.
- Описание свойств COM для классов, методов и интерфейсов.
- Вызов неуправляемого кода с помощью атрибута
DllImport
.- Описание названия, версии, описания или торговой марки вашей сборки.
- Описание сериализуемых членов класса.
- Описание соответствия членов класса узлам XML при XML-сериализации.
- Описание требований безопасности для методов.
- Управление оптимизацией JIT-компилятора.
- Получение информации об объекте, вызвавшем метод.
Источники:
- Джеффри Рихтер “CLR via C#”. 3-е изд. – СПб.: Питер, 2012. Глава 18.
- https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/attributes/
День пятьдесят пятый. #TipsAndTricks
Улучшите читаемость чисел, используя Разделитель Цифр в C# 7
Иногда в коде приходится использовать литеральные значения чисел. Иногда они маленькие, а иногда достаточно большие. В случае с маленькими числами проблем нет, но длинные числа иногда тяжело читать. C# 7.0 позволяет использовать разделитель ‘
Улучшите читаемость чисел, используя Разделитель Цифр в C# 7
Иногда в коде приходится использовать литеральные значения чисел. Иногда они маленькие, а иногда достаточно большие. В случае с маленькими числами проблем нет, но длинные числа иногда тяжело читать. C# 7.0 позволяет использовать разделитель ‘
_
’ в литералах для улучшения читаемости вашего кода. Разделитель никак не влияет на число, вы можете использовать такое число так же, как любую другую целочисленную переменную. Разделители также могут применяться в двоичных и шестнадцатеричных выражениях чисел. Начиная с версии 7.2 можно отделять также части '0b
' и '0x
':var number = 123_456_789;
var binary = 0b111_1110_0011;
var binary_7_2 = 0b_111_1110_0011; // C# 7.2+
var hex = 0x7_e3;
var hex_7_2 = 0x_7e3; // C# 7.2+
День пятьдесят шестой. #ЗаметкиНаПолях
Общие атрибуты
1. Глобальные атрибуты
Применяются к сборке или модулю в целом. Например,
Различают три категории атрибутов сборки:
- атрибуты идентификации сборки: обязательные атрибуты для сборки (
- информационные атрибуты: дополнительная информация о сборке (
- атрибуты манифеста сборки (
2. Атрибут Obsolete
Обозначает элементы программы, не рекомендуемые для дальнейшего использования. Выдаёт предупреждение компилятора или ошибку компиляции в зависимости от настройки:
3. Условный атрибут
Условный атрибут ставит выполнение метода в зависимость от идентификатора препроцессора, определяемого в коде следующим образом:
Условные атрибуты можно совмещать. Тогда метод будет исполнен, если хотя бы один из идентификаторов определён:
Используя атрибуты Caller Info, вы можете получить информацию об объекте, вызвавшем метод: имя свойства или метода, путь к исходному файлу и номер строки в файле. Атрибуты указываются для необязательных параметров метода, которые имеют значения по умолчанию:
Общие атрибуты
1. Глобальные атрибуты
Применяются к сборке или модулю в целом. Например,
AssemblyVersion
используется для указания версии сборки:[assembly: AssemblyVersion("1.0.0.0")]В коде глобальные атрибуты располагаются после директив высшего уровня и перед любыми объявлениями классов, модулей или пространств имён. В проектах C# они помещаются в файл
AssemblyInfo.cs
.Различают три категории атрибутов сборки:
- атрибуты идентификации сборки: обязательные атрибуты для сборки (
AssemblyName
, AssemblyVersion
, AssemblyCulture
, AssemblyFlags
),- информационные атрибуты: дополнительная информация о сборке (
AssemblyProduct
, AssemblyTrademark
, AssemblyInformationalVersion
, AssemblyCompany
, AssemblyCopyright
, AssemblyFileVersion
, CLSCompliant
)- атрибуты манифеста сборки (
AssemblyTitle
, AssemblyDescription
, AssemblyConfiguration
, AssemblyDefaultAlias
).2. Атрибут Obsolete
Обозначает элементы программы, не рекомендуемые для дальнейшего использования. Выдаёт предупреждение компилятора или ошибку компиляции в зависимости от настройки:
[System.Obsolete("use class B")]В этом примере использование класса
class A
{
public void Method() { }
}
class B
{
[System.Obsolete("use NewMethod", true)]
public void OldMethod() { }
public void NewMethod() { }
}
A
приведёт к предупреждению компилятора, а использование метода OldMethod
класса B
к ошибке, т.к. второй параметр конструктора атрибута (error
) установлен в true
. Первый строковый параметр (message
) используется как сообщение компилятора. Он не обязательный, но его рекомендуется задавать.3. Условный атрибут
Условный атрибут ставит выполнение метода в зависимость от идентификатора препроцессора, определяемого в коде следующим образом:
#define CONDITION1Чаще всего он используется с идентификатором
DEBUG
, для включения функций трассировки и ведения журнала для отладочных сборок (но не в релизе):[Conditional("DEBUG")]Атрибут определяет, вызывается или нет метод, помеченный им. Если идентификатор не определён, метод не вызывается. Условный метод должен быть определён в классе или структуре и не должен возвращать значений.
static void DebugMethod() { /*…*/ }
Условные атрибуты можно совмещать. Тогда метод будет исполнен, если хотя бы один из идентификаторов определён:
[Conditional("A"), Conditional("B")]4. Атрибуты Caller Info
static void DoIfAorB() { /*…*/ }
Используя атрибуты Caller Info, вы можете получить информацию об объекте, вызвавшем метод: имя свойства или метода, путь к исходному файлу и номер строки в файле. Атрибуты указываются для необязательных параметров метода, которые имеют значения по умолчанию:
using System.Diagnostics;Источник: https://docs.microsoft.com/ru-ru/dotnet/csharp/programming-guide/concepts/attributes/common-attributes
using System.Runtime.CompilerServices;
public void DoProcessing()
{
TraceMessage("Something happened.");
}
public void TraceMessage(string message,
[CallerMemberName] string memberName = "",
[CallerFilePath] string sourceFilePath = "",
[CallerLineNumber] int sourceLineNumber = 0)
{
Trace.WriteLine("message: " + message);
Trace.WriteLine("member name: " + memberName);
Trace.WriteLine("source file path: " + sourceFilePath);
Trace.WriteLine("source line number: " + sourceLineNumber);
}
// Пример вывода:
// message: Something happened.
// member name: DoProcessing
// source file path: c:\Visual Studio Projects\CallerInfoCS\CallerInfoCS\Form1.cs
// source line number: 31
👍1
День пятьдесят седьмой. #TipsAndTricks
8. Вспомогательные Функции
В C# 7.0 вы можете определить вспомогательную функцию внутри метода. Локальная функция может получать доступ ко всем локальным переменным, а также может использовать лямбда-выражение и даже конструкцию async-await. Но эта функция недоступна извне метода.
Можно использовать более одной локальной функции, а также вложенные друг в друга локальные функции (см. рисунок).
Источник: https://dailydotnettips.com/
8. Вспомогательные Функции
В C# 7.0 вы можете определить вспомогательную функцию внутри метода. Локальная функция может получать доступ ко всем локальным переменным, а также может использовать лямбда-выражение и даже конструкцию async-await. Но эта функция недоступна извне метода.
class Program
{
static void Main(string[] args)
{
int val = 100;
int MyLocalFunction(int value1, int value2)
{
return val + value1 + value2;
}
Console.WriteLine(MyLocalFunction(10, 10));
}
}
Можно использовать более одной локальной функции, а также вложенные друг в друга локальные функции (см. рисунок).
Источник: https://dailydotnettips.com/
День пятьдесят восьмой. #ЗаметкиНаПолях
Создание класса атрибута
Вы можете создавать свои атрибуты, определяя класса атрибута, производный от класса
- все неабстрактные атрибуты должны содержать хотя бы один открытый конструктор;
- класс атрибута следует рассматривать как логический контейнер состояния, поэтому должен быть крайне простым, без открытых методов, событий и других членов;
- члены класса должны ограничиваться небольшим набором примитивных типов данных, перечислимыми типами и одномерными массивами (но это не рекомендуется).
Использовать атрибут можно следующим образом:
-
-
-
- Джеффри Рихтер “CLR via C#”. 3-е изд. – СПб.: Питер, 2012. Глава 18.
- https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/attributes/
Создание класса атрибута
Вы можете создавать свои атрибуты, определяя класса атрибута, производный от класса
Attribute
. Допустим, вы хотите отмечать имя программиста, создавшего тип:public class AuthorAttribute : System.Attribute- суффикс
{
private string name;
public double version;
public AuthorAttribute(string name)
{
this.name = name;
version = 1.0;
}
}
Attribute
в названии класса не обязателен, но соответствует стандарту наименования; - все неабстрактные атрибуты должны содержать хотя бы один открытый конструктор;
- класс атрибута следует рассматривать как логический контейнер состояния, поэтому должен быть крайне простым, без открытых методов, событий и других членов;
- члены класса должны ограничиваться небольшим набором примитивных типов данных, перечислимыми типами и одномерными массивами (но это не рекомендуется).
Использовать атрибут можно следующим образом:
[Author("P. Ackerman", version = 1.1)]К классу атрибута можно также применить атрибут типа
class SampleClass { /* … */ }
AttributeUsage
, который задаёт следующие параметры:-
AttributeTargets
– перечисление целевых объектов для атрибута (по умолчанию AttributeTargets.All
);-
AllowMultiple
– допустимо ли многократное использование атрибута (по умолчанию false
);-
Inherited
– будет ли атрибут наследоваться потомками класса (по умолчанию true
).[System.AttributeUsage(Источники:
System.AttributeTargets.Class |
System.AttributeTargets.Struct,
AllowMultiple = true,
Inherited = false)
]
- Джеффри Рихтер “CLR via C#”. 3-е изд. – СПб.: Питер, 2012. Глава 18.
- https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/attributes/
День пятьдесят девятый. #TipsAndTricks
9. Форматирование выражений в отладчике Visual Studio
Вы можете изменить формат отображения значений в окне Watch, используя форматирование выражений. Чтобы это сделать, введите выражение, за ним поставьте запятую и укажите формат.
-
-
Объекты:
-
-
-
-
Поведение:
-
-
Источник: https://docs.microsoft.com/en-us/visualstudio/debugger/format-specifiers-in-csharp?view=vs-2017
9. Форматирование выражений в отладчике Visual Studio
Вы можете изменить формат отображения значений в окне Watch, используя форматирование выражений. Чтобы это сделать, введите выражение, за ним поставьте запятую и укажите формат.
Примитивные типы:-
d
– Десятичное целое число (было: 0x0065
, станет: 101
).-
h
– Шестнадцатеричное целое число (было: 61541
, станет: 0x0000F065
).-
nq
– строка без кавычек (было: "My String"
, станет: My String
).Объекты:
-
dynamic
– Отображает указанный объект в динамическом представлении. -
hidden
– Отображает все члены класса, включая непубличные.-
raw
– Отображает элемент так, как он отображается в представлении Raw. Действительно только для прокси-объектов, например, Dictionary<T>
.-
results
– Используется с переменной типа, реализующего IEnumerable
или IEnumerable<T>
, обычно являющейся результатом запроса. Отображает только члены, содержащие результат запроса. Поведение:
-
ac
– Принудительный перерасчет значения выражения.-
nse
– Указывает поведение «Без побочных эффектов». Если выражение не может быть интерпретировано, и значение может быть найдено только оценкой (например, с помощью вызова функции), вы получите ошибку. Источник: https://docs.microsoft.com/en-us/visualstudio/debugger/format-specifiers-in-csharp?view=vs-2017
День шестидесятый. #TipsAndTricks
10. Управление полем значения в отладчике
Мощь современного отладчика заключается в отображении данных объекта при отладке в простой и понятной форме. Поэтому, когда отладчик отображает эту информацию, он должен показывать наиболее интересные значения сразу. К сожалению, отладчику трудно анализировать различные объекты и выделять в них «самое важное». Единственным универсальным решением будет контроль за отображением значений в отладчике, что состоит в добавлении атрибутов к объектам.
Отладка с применением атрибутов даёт разработчику типа возможность указать, как объект будет выглядеть в отладчике. Это достигается применением атрибута
Если вы хотите посмотреть свойства объекта
Источник: https://devblogs.microsoft.com/visualstudio/7-hidden-gems-in-visual-studio-2017/
10. Управление полем значения в отладчике
Мощь современного отладчика заключается в отображении данных объекта при отладке в простой и понятной форме. Поэтому, когда отладчик отображает эту информацию, он должен показывать наиболее интересные значения сразу. К сожалению, отладчику трудно анализировать различные объекты и выделять в них «самое важное». Единственным универсальным решением будет контроль за отображением значений в отладчике, что состоит в добавлении атрибутов к объектам.
Отладка с применением атрибутов даёт разработчику типа возможность указать, как объект будет выглядеть в отладчике. Это достигается применением атрибута
DebuggerDisplay
. Допустим, вы отлаживаете следующий код:class PersonЕсли вы установите точку прерывания на закрывающей скобке метода
{
public string FirstName;
public string LastName;
public Person(string first, string last)
{
this.FirstName = first;
this.LastName = last;
}
public string FullName {get => $"{LastName}, {FirstName}";} }
class Program
{
static void Main(string[] args)
{
List<Person> presidents = new List<Person>
{
new Person("George", "Washington"),
new Person("John", "Adams"),
new Person("Thomas", "Jefferson"),
new Person("James", "Madison"),
new Person("James", "Monroe")
};
}
}
Main
и посмотрите на значения элементов списка, вы увидите малозначащую строку {Person}
(см. рисунок ниже).Если вы хотите посмотреть свойства объекта
James Madison
, то вы должны знать, что он четвёртый в списке. Можно переопределить метод ToString
типа Person
, тогда отладчик вызовет его. Но это приведёт к оценке значения функции, что в сотню раз медленнее обычного вывода значения данных. Кроме того, вывод в отладчике может отличаться от желаемого вывода метода ToString
в программе. Поэтому определите атрибут DebuggerDisplay
следующим образом:[DebuggerDisplay("Name: {FullName,nq}")]Здесь атрибут приводит к выводу значения свойства
class Person
FullName
без кавычек (формат ‘nq
’ – см. форматы отладчика в предыдущем посте).Источник: https://devblogs.microsoft.com/visualstudio/7-hidden-gems-in-visual-studio-2017/
День шестьдесят первый. #TipsAndTricks
11. Сниппеты
Многие наверняка знакомы со встроенными в Visual Stodio Сниппетами, но стоит отметить, что они расширяемые. Вы можете добавлять свои сниппеты. Директория хранения сниппетов по умолчанию:
Давайте для примера создадим сниппет var для определения переменной:
Источник: https://devblogs.microsoft.com/visualstudio/7-hidden-gems-in-visual-studio-2017/
11. Сниппеты
Многие наверняка знакомы со встроенными в Visual Stodio Сниппетами, но стоит отметить, что они расширяемые. Вы можете добавлять свои сниппеты. Директория хранения сниппетов по умолчанию:
%имяпользователя%\Documents\Visual Studio 2017\Code Snippets\Visual C#\My Code Snippets
.Давайте для примера создадим сниппет var для определения переменной:
<?xml version="1.0" encoding="utf-8" ?>Теперь, когда вы введёте var в файле C# и дважды нажмёте tab, будет вставлен следующий код:
<CodeSnippets xmlns="https://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
<CodeSnippet Format="1.0.0">
<Header>
<Title>Var</Title>
<Shortcut>var</Shortcut>
<Description>Code snippet for instantiating an object with full type info</Description>
<Author>Anson Horton</Author>
<SnippetTypes>
<SnippetType>Expansion</SnippetType>
</SnippetTypes>
</Header>
<Snippet>
<Declarations>
<Literal>
<ID>type</ID>
<Default>Example</Default>
<ToolTip>The type to construct</ToolTip>
</Literal>
<Literal>
<ID>variable</ID>
<Default>example</Default>
<ToolTip>The variable name</ToolTip>
</Literal>
<Literal>
<ID>args</ID>
<Default></Default>
<ToolTip>The constructor arguments</ToolTip>
</Literal>
</Declarations>
<Code Language="csharp">
<![CDATA[$type$ $variable$ = new $type$($args$);$end$]]>
</Code>
</Snippet>
</CodeSnippet>
</CodeSnippets>
Example example = new Example();После этого можно клавишей tab перемещаться по литералам и изменять их, при этом все ссылки на одинаковый литерал будут обновляться автоматически. Сниппеты поддерживаются для многих языков в Visual Studio, включая Visual Basic, C#, CSS, HTML, JavaScript, TSQL, TypeScript, Visual C++, XAML и XML.
Источник: https://devblogs.microsoft.com/visualstudio/7-hidden-gems-in-visual-studio-2017/
День шестьдесят второй. #ЗаметкиНаПолях
Исключения. Начало
Конструируя тип, мы заранее пытаемся представить, в каких ситуациях он будет использоваться. Форма определения членов типа (типы данных свойств, параметры методов, возвращаемые значения и т.п.) становится интерфейсом типа. Члены типа определяют допустимые действия с типом и его экземплярами. Если член типа не может решить возложенную на него задачу, должно появляться исключение.
Пример обработки исключений:
1. Исключения представляют собой типы, производные в конечном счете от
2. Блок
3. Когда внутри такого блока try возникает исключение, поток управления переходит к первому подходящему обработчику исключений в стеке вызовов. В C# ключевое слово
4. Если блок
5. Просмотр блоков
6. Если для созданного исключения не существует обработчиков, выполнение программы прекращается с сообщением об ошибке.
7. Программа может явным образом создавать исключения с помощью ключевого слова
8. Объекты исключения содержат подробные сведения об ошибке, например состояние стека вызовов и текстовое описание ошибки.
9. Код в блоке
Источники:
- Джеффри Рихтер “CLR via C#”. 3-е изд. – СПб.: Питер, 2012. Глава 20.
- https://docs.microsoft.com/ru-ru/dotnet/csharp/programming-guide/exceptions/
Исключения. Начало
Конструируя тип, мы заранее пытаемся представить, в каких ситуациях он будет использоваться. Форма определения членов типа (типы данных свойств, параметры методов, возвращаемые значения и т.п.) становится интерфейсом типа. Члены типа определяют допустимые действия с типом и его экземплярами. Если член типа не может решить возложенную на него задачу, должно появляться исключение.
Пример обработки исключений:
try {Свойства исключений:
// код, требующий корректного восстановления или очистки ресурсов при возникновении исключения
}
catch (InvalidOperationException) {
// обработка исключения типа InvalidOperationException
}
catch (IOException ex) {
// обработка исключения типа IOException
// информация об исключении будет в переменной ex
}
catch {
// обработка остальных типов исключений
}
finally {
// код очистки ресурсов после операций блока try
// этот код исполняется ВСЕГДА
}
// код после блока finally выполняется, если не было сгенерировано исключений, либо если они были перехвачены блоками catch, а новых не генерировалось
1. Исключения представляют собой типы, производные в конечном счете от
System.Exception
.2. Блок
try
используется для выполнения таких инструкций, которые могут создавать исключения. Блок try
должен быть связан хотя бы с одним блоком catch
или finally
.3. Когда внутри такого блока try возникает исключение, поток управления переходит к первому подходящему обработчику исключений в стеке вызовов. В C# ключевое слово
catch
обозначает обработчик исключений. Если исключения не возникает, код в блоке catch не выполняется.4. Если блок
catch
определяет переменную исключения, ее можно использовать для получения дополнительных сведений о типе созданного исключения.5. Просмотр блоков
catch
осуществляется сверху вниз, поэтому исключения должны указываться в порядке от более специализированных к их базовым классам (если они есть) и наконец, к классу System.Exception
. Иначе компилятор сообщит об ошибке, т.к. более узкоспециализированные блоки окажутся недостижимыми. 6. Если для созданного исключения не существует обработчиков, выполнение программы прекращается с сообщением об ошибке.
7. Программа может явным образом создавать исключения с помощью ключевого слова
throw
.8. Объекты исключения содержат подробные сведения об ошибке, например состояние стека вызовов и текстовое описание ошибки.
9. Код в блоке
finally
выполняется даже в том случае, если создано исключение. Используйте блок finally
, чтобы высвободить ресурсы, например закрыть потоки и файлы, которые были открыты внутри блока try
. Блок finally
помещается после всех блоков catch
. Одному блоку try может соответствовать только один блок finally
.Источники:
- Джеффри Рихтер “CLR via C#”. 3-е изд. – СПб.: Питер, 2012. Глава 20.
- https://docs.microsoft.com/ru-ru/dotnet/csharp/programming-guide/exceptions/
День шестьдесят третий.
Visual Studio 2019
Visual Studio 2019 стала доступна для скачивания. С её помощью вы и ваша команда сможете стать ещё более продуктивными в проектировании текущих и будущих проектов в среде, для которой важно каждое нажатие кнопки.
Версия 2019 содержит улучшения 2017й версии в нескольких областях. Она помогает вам быстро получить доступ к коду, упрощая создание клонов в репозитории Git или открытие существующих проектов или папок. Также улучшения коснулись экрана выбора шаблонов при старте нового проекта. При написании кода вы увидите, что улучшилась навигация по коду и добавлено много вариантов рефакторинга, а также показателей состояния документа и очистка кода в один клик с применением сразу нескольких правил рефакторинга. Также улучшена отладка, включая точки останова на данных в приложениях .Net Core, которые помогут вам прерывать выполнение при изменении выбранных вами значений. Кроме того, добавлен помощник в написании кода, основанный на искусственном интеллекте, IntelliCode.
Эти нововведения будут работать как на существующих проектах, так и в новых, от кроссплатформенных приложений на C++ до мобильных приложений .Net для Android и iOS, написанных на Xamarin, до облачных сервисов на Azure. Цель Visual Studio 2019 – поддерживать эти проекты от разработки, через тестирование и отладку до развёртывания, минимизируя для вас необходимость переключаться между разными приложениями, порталами и сайтами.
Скачать Релиз-кандидат Visual Studio 2019 можно здесь: https://visualstudio.microsoft.com/ru/downloads/
Источник: https://devblogs.microsoft.com/visualstudio/visual-studio-2019-code-faster-work-smarter-create-the-future/
Visual Studio 2019
Visual Studio 2019 стала доступна для скачивания. С её помощью вы и ваша команда сможете стать ещё более продуктивными в проектировании текущих и будущих проектов в среде, для которой важно каждое нажатие кнопки.
Версия 2019 содержит улучшения 2017й версии в нескольких областях. Она помогает вам быстро получить доступ к коду, упрощая создание клонов в репозитории Git или открытие существующих проектов или папок. Также улучшения коснулись экрана выбора шаблонов при старте нового проекта. При написании кода вы увидите, что улучшилась навигация по коду и добавлено много вариантов рефакторинга, а также показателей состояния документа и очистка кода в один клик с применением сразу нескольких правил рефакторинга. Также улучшена отладка, включая точки останова на данных в приложениях .Net Core, которые помогут вам прерывать выполнение при изменении выбранных вами значений. Кроме того, добавлен помощник в написании кода, основанный на искусственном интеллекте, IntelliCode.
Эти нововведения будут работать как на существующих проектах, так и в новых, от кроссплатформенных приложений на C++ до мобильных приложений .Net для Android и iOS, написанных на Xamarin, до облачных сервисов на Azure. Цель Visual Studio 2019 – поддерживать эти проекты от разработки, через тестирование и отладку до развёртывания, минимизируя для вас необходимость переключаться между разными приложениями, порталами и сайтами.
Скачать Релиз-кандидат Visual Studio 2019 можно здесь: https://visualstudio.microsoft.com/ru/downloads/
Источник: https://devblogs.microsoft.com/visualstudio/visual-studio-2019-code-faster-work-smarter-create-the-future/
Visual Studio
Скачать Инструменты Visual Studio — установить бесплатно для Windows, Mac, Linux
Скачайте IDE Visual Studio или VS Code бесплатно. Испытайте выпуск Visual Studio Professional или Visual Studio Enterprise в Windows, Mac.
День шестьдесят четвёртый. #ЗаметкиНаПолях
Исключения. Продолжение
Советы по обработке исключений
1. Если блок
2. Программа может явным образом создавать исключения с помощью ключевого слова
3. Объём блока кода внутри
4. При отладке в Visual Studio для просмотра выброшенного исключения нужно добавить в окно Watch специальную переменную
5. Если обнаружится, что состояние приложения осталось испорченным даже после восстановительных операций в блоках
Приёмы работы с исключениями:
1. Активно используйте блоки finally для очистки ресурсов.
- В C# блоки
2. Не надо перехватывать все исключения.
- К примеру, код библиотеки не может знать, как он будет использоваться в различных приложениях. Исключение должно передаваться вверх по стеку вызовов и обрабатываться кодом приложения. Допустимо перехватывать исключения
3. Корректное восстановление после исключения.
- Иногда заранее известны типы исключений, источником которых может стать метод. Только полностью осознавая обстоятельства, вызывающие конкретные типы исключений, можно перехватывать их и позволять приложению продолжать работу после восстановления.
4. Отмена незавершённых операций при невосстановимых исключениях.
- Когда бизнес-логика требует отменить все ранее выполненные действия при возникновении исключения (банковская транзакция, сериализация группы объектов, транзакция в базе данных и т.п.), имеет смысл перехватывать ВСЕ возможные исключения, отменять сделанные изменения, но обязательно выбрасывать исключение повторно.
5. Скрытие деталей реализации для сохранения контракта
- Иногда бывает полезно после перехвата одного исключения, выбросить исключение другого типа для сохранения деталей реализации. Например, создать исключение
- При использовании этого приёма стоит перехватывать только те исключения, обстоятельства возникновения которых вы хорошо понимаете. Здесь мы обманываем вызывающий код сообщая неправду о том, что пошло не так, и о месте сбоя. Трассировка стека укажет только место выброса исключения
Источники:
- Джеффри Рихтер “CLR via C#”. 3-е изд. – СПб.: Питер, 2012. Глава 20.
- https://docs.microsoft.com/ru-ru/dotnet/csharp/programming-guide/exceptions/
Исключения. Продолжение
Советы по обработке исключений
1. Если блок
catch
определяет переменную исключения, ее можно использовать для получения дополнительных сведений о типе созданного исключения. Эту переменную обычно стоит рассматривать как доступную только для чтения, однако можно добавлять нужную информацию в коллекцию её свойства Data
.2. Программа может явным образом создавать исключения с помощью ключевого слова
throw
.3. Объём блока кода внутри
try
зависит от управления состоянием. Если внутри блока вы собираетесь выполнить набор операций, каждая из которых может стать причиной исключения одного и того же типа, но при этом вы хотите обработать эти исключения по-разному, имеет смысл поместить операции в разные блоки try
.4. При отладке в Visual Studio для просмотра выброшенного исключения нужно добавить в окно Watch специальную переменную
$exception
.5. Если обнаружится, что состояние приложения осталось испорченным даже после восстановительных операций в блоках
catch
или finally
, имеет смысл его удалить, чтобы не создавать дополнительных проблем. Это делается методом AppDomain.Unload
. После этого приложение перезагружается, чтобы состояние инициализировалось нормально. Если состояние кажется настолько плохим, что имеет смысл завершить работу приложения, используйте статический метод Environment.FailFast
. Он завершает процесс без выполнения активных блоков try/finally
и без вызовов метода Finalize
.Приёмы работы с исключениями:
1. Активно используйте блоки finally для очистки ресурсов.
- В C# блоки
try/finally
автоматически создаются компилятором для некоторых конструкций: в lock
отключается блокировка, в using
вызывается метод Dispose
объекта, в foreach
вызывается метод Dispose объекта IEnumerator
, в деструкторах вызывается метод Finalize базового класса.2. Не надо перехватывать все исключения.
- К примеру, код библиотеки не может знать, как он будет использоваться в различных приложениях. Исключение должно передаваться вверх по стеку вызовов и обрабатываться кодом приложения. Допустимо перехватывать исключения
System.Exception
только при условии их повторной генерации в конце блока catch
.3. Корректное восстановление после исключения.
- Иногда заранее известны типы исключений, источником которых может стать метод. Только полностью осознавая обстоятельства, вызывающие конкретные типы исключений, можно перехватывать их и позволять приложению продолжать работу после восстановления.
4. Отмена незавершённых операций при невосстановимых исключениях.
- Когда бизнес-логика требует отменить все ранее выполненные действия при возникновении исключения (банковская транзакция, сериализация группы объектов, транзакция в базе данных и т.п.), имеет смысл перехватывать ВСЕ возможные исключения, отменять сделанные изменения, но обязательно выбрасывать исключение повторно.
5. Скрытие деталей реализации для сохранения контракта
- Иногда бывает полезно после перехвата одного исключения, выбросить исключение другого типа для сохранения деталей реализации. Например, создать исключение
RecordNotFoundException
для операций поиска в файле или базе данных и выбрасывать его вместо исключений типа FileNotFound
, IOException
или исключений, связанных с доступом к базе данных.- При использовании этого приёма стоит перехватывать только те исключения, обстоятельства возникновения которых вы хорошо понимаете. Здесь мы обманываем вызывающий код сообщая неправду о том, что пошло не так, и о месте сбоя. Трассировка стека укажет только место выброса исключения
RecordNotFoundException
, но не изначального. Это может затруднить отладку.Источники:
- Джеффри Рихтер “CLR via C#”. 3-е изд. – СПб.: Питер, 2012. Глава 20.
- https://docs.microsoft.com/ru-ru/dotnet/csharp/programming-guide/exceptions/
👍1
День шестьдесят пятый. #TipsAndTricks
13. Просмотр производных типов
Иногда бывает полезно посмотреть все типы производные от базового класса. Это особенно актуально для типов из больших фреймворков вроде .NET Framework. Это можно сделать в окне Object Browser. Хитрость в том, что по умолчанию просмотр объектов ограничен вашим решением («My Solution» в списке Browse). Но значение можно изменить. Например, посмотрим типы из библиотеки .NET Framework 4.7.2 (см. рисунок).
Теперь, если вы хотите посмотреть типы производные от
Это работает для любой сборки или фреймворка. Но, чтобы использовать это для ссылок, подключённых к вашему проекту, сначала нужно добавить их в отдельный набор «custom component set», нажав на … справа от выпадающего списка Browse.
Источник: https://devblogs.microsoft.com/visualstudio/7-hidden-gems-in-visual-studio-2017/
13. Просмотр производных типов
Иногда бывает полезно посмотреть все типы производные от базового класса. Это особенно актуально для типов из больших фреймворков вроде .NET Framework. Это можно сделать в окне Object Browser. Хитрость в том, что по умолчанию просмотр объектов ограничен вашим решением («My Solution» в списке Browse). Но значение можно изменить. Например, посмотрим типы из библиотеки .NET Framework 4.7.2 (см. рисунок).
Теперь, если вы хотите посмотреть типы производные от
System.IO.Stream
, просто найдите этот тип, используя строку поиска и разверните папку «Derived Types». Возможно, придётся немного подождать результатов.Это работает для любой сборки или фреймворка. Но, чтобы использовать это для ссылок, подключённых к вашему проекту, сначала нужно добавить их в отдельный набор «custom component set», нажав на … справа от выпадающего списка Browse.
Источник: https://devblogs.microsoft.com/visualstudio/7-hidden-gems-in-visual-studio-2017/
👍2
День шестьдесят шестой. #ЗаметкиНаПолях
Исключения. Продолжение
Генерация исключений
При реализации своего метода нужно генерировать исключение, если метод не в состоянии решить возложенную на него задачу. При этом важно учесть два фактора:
1. Понять, к какому типу, производному от
2. Решить, какое сообщение должно быть передано конструктору исключения. Исключение должно содержать детальную информацию, почему метод не смог решить свою задачу. Обычно конечные пользователи приложения не имеют доступа к исходному коду, а приложения скрывают от них детали ошибок, поэтому в сообщение можно смело помещать всю техническую информацию, необходимую для устранения дефекта.
Выражение throw
Начиная с C# 7.0 throw можно использовать в контекстах, которые ранее не поддерживались:
1. Тернарный оператор
До C# 7.0 нужно было использовать if/else:
3. Лямбда-выражение или лямбда-метод
- Джеффри Рихтер “CLR via C#”. 3-е изд. – СПб.: Питер, 2012. Глава 20.
- https://docs.microsoft.com/ru-ru/dotnet/csharp/language-reference/keywords/throw
Исключения. Продолжение
Генерация исключений
При реализации своего метода нужно генерировать исключение, если метод не в состоянии решить возложенную на него задачу. При этом важно учесть два фактора:
1. Понять, к какому типу, производному от
System.Exception
будет относиться ваше исключение. Можно использовать один из типов FCL, либо создать собственный тип. При этом в иерархии типов должно быть как можно меньше базовых классов, т.к. перехват ошибок базового класса также перехватит и ошибки всех производных классов, а это может быть нежелательно.2. Решить, какое сообщение должно быть передано конструктору исключения. Исключение должно содержать детальную информацию, почему метод не смог решить свою задачу. Обычно конечные пользователи приложения не имеют доступа к исходному коду, а приложения скрывают от них детали ошибок, поэтому в сообщение можно смело помещать всю техническую информацию, необходимую для устранения дефекта.
Выражение throw
Начиная с C# 7.0 throw можно использовать в контекстах, которые ранее не поддерживались:
1. Тернарный оператор
До C# 7.0 нужно было использовать if/else:
private static void DisplayFirstNumber(string[] args)2. Оператор объединения с NULL
{
string arg = args.Length >= 1 ? args[0] :
throw new ArgumentException("Массив пустой");
}
public string Name
{
get => name;
set => name = value ??
throw new ArgumentNullException("Имя не может быть null", nameof(value));
}
3. Лямбда-выражение или лямбда-метод
DateTime ToDateTime(IFormatProvider provider) =>Источники:
throw new InvalidCastException("Преобразование в DateTime не поддерживается.");
- Джеффри Рихтер “CLR via C#”. 3-е изд. – СПб.: Питер, 2012. Глава 20.
- https://docs.microsoft.com/ru-ru/dotnet/csharp/language-reference/keywords/throw
День шестьдесят седьмой. #Оффтоп
Нашёл ещё один интересный канал на YouTube про C# и .Net разработку - IAmTimCorey. https://www.youtube.com/user/IAmTimCorey/ Сразу предупреждаю, все видео на английском, поэтому кто ещё не изучил... это ваши проблемы)))
Тим - разработчик софта, тренер и консультант, имеющий награды Microsoft MVP, PMP и MCP, а также Intel Software Innovator. Цель канала - упростить изучение разработки ПО. Видео на канале самые разнообразные: базовые понятия, инструменты и советы по C#, паттерны проектирования, создание приложения на C# с нуля, связанные технологии (ASP.NET MVC, Azure, SQL Data Tools и т.п.).
Видео не из коротких (от 40 до 90 минут), потому что объясняется всё достаточно подробно. Но и нельзя сказать, что сильно затянуто. Я смотрю для повторения темы либо фоном, либо на скорости 1.5x. Кроме того, есть подборка Weekly Challenge. Короткое, на пару минут, видео с заданием по C# на определённую тему. Можно решить самому, а потом посмотреть предложенное решение по ссылке в описании к видео. Самое главное, что канал не заброшен. Последнее Weekly Challenge совсем свежее, выдано 4 апреля.
Кроме того, у Тима есть сайт с текстовыми версиями и решениями Weekly Challenge, а также блогом: https://www.iamtimcorey.com
Нашёл ещё один интересный канал на YouTube про C# и .Net разработку - IAmTimCorey. https://www.youtube.com/user/IAmTimCorey/ Сразу предупреждаю, все видео на английском, поэтому кто ещё не изучил... это ваши проблемы)))
Тим - разработчик софта, тренер и консультант, имеющий награды Microsoft MVP, PMP и MCP, а также Intel Software Innovator. Цель канала - упростить изучение разработки ПО. Видео на канале самые разнообразные: базовые понятия, инструменты и советы по C#, паттерны проектирования, создание приложения на C# с нуля, связанные технологии (ASP.NET MVC, Azure, SQL Data Tools и т.п.).
Видео не из коротких (от 40 до 90 минут), потому что объясняется всё достаточно подробно. Но и нельзя сказать, что сильно затянуто. Я смотрю для повторения темы либо фоном, либо на скорости 1.5x. Кроме того, есть подборка Weekly Challenge. Короткое, на пару минут, видео с заданием по C# на определённую тему. Можно решить самому, а потом посмотреть предложенное решение по ссылке в описании к видео. Самое главное, что канал не заброшен. Последнее Weekly Challenge совсем свежее, выдано 4 апреля.
Кроме того, у Тима есть сайт с текстовыми версиями и решениями Weekly Challenge, а также блогом: https://www.iamtimcorey.com
День шестьдесят восьмой. #Оффтоп
Я уже писал, что не считаю себя труЪ программистом. В моём понимании настоящие программисты работают над созданием сложных систем и эффективных алгоритмов, создают операционные системы и языки программирования, а также программы ИИ, обыгрывающие человека в шахматы или го. А остальные, и я в том числе, разработчики, которые пользуются плодами первых. И 99% нашей работы, давайте по-честноку, сбор целого из готовых кусочков и небольшая доработка напильником, без сильного напряжения мозга. Если что, я не хотел никого обидеть)))
А поэтому мне всегда нравились ролики, в которых описываются либо базовые алгоритмы (о них, может, сделаю отдельную серию постов), либо решения интересных задач из реального мира. Вот, к примеру, наткнулся в рекомендациях ютуба на видео из курса MIT 6.S095 «Programming for the Puzzled». https://www.youtube.com/watch?v=auK3PSZoidc
В часовом видео, оригинально названном «Вы больше никогда не захотите играть в судоку», описан алгоритм нахождения решения судоку. Сначала прямо в лоб, затем применяются некоторые усовершенствования, чтобы оптимизировать его работу. И какой бы трудной задача ни казалась изначально, в реальности всё решение сводится к 40 строчкам кода и не содержит взрывающих мозг сложностей. Кстати, прекрасный пример красивого и эффективного применения рекурсии. Код в видео написан на Python, но, думаю, что даже тем, кто не знаком с синтаксисом этого языка, будет в принципе понятна суть. Да, и, как это всегда бывает с самыми интересными материалами по программированию, видео на английском.
Я уже писал, что не считаю себя труЪ программистом. В моём понимании настоящие программисты работают над созданием сложных систем и эффективных алгоритмов, создают операционные системы и языки программирования, а также программы ИИ, обыгрывающие человека в шахматы или го. А остальные, и я в том числе, разработчики, которые пользуются плодами первых. И 99% нашей работы, давайте по-честноку, сбор целого из готовых кусочков и небольшая доработка напильником, без сильного напряжения мозга. Если что, я не хотел никого обидеть)))
А поэтому мне всегда нравились ролики, в которых описываются либо базовые алгоритмы (о них, может, сделаю отдельную серию постов), либо решения интересных задач из реального мира. Вот, к примеру, наткнулся в рекомендациях ютуба на видео из курса MIT 6.S095 «Programming for the Puzzled». https://www.youtube.com/watch?v=auK3PSZoidc
В часовом видео, оригинально названном «Вы больше никогда не захотите играть в судоку», описан алгоритм нахождения решения судоку. Сначала прямо в лоб, затем применяются некоторые усовершенствования, чтобы оптимизировать его работу. И какой бы трудной задача ни казалась изначально, в реальности всё решение сводится к 40 строчкам кода и не содержит взрывающих мозг сложностей. Кстати, прекрасный пример красивого и эффективного применения рекурсии. Код в видео написан на Python, но, думаю, что даже тем, кто не знаком с синтаксисом этого языка, будет в принципе понятна суть. Да, и, как это всегда бывает с самыми интересными материалами по программированию, видео на английском.
YouTube
Puzzle 8: You Won't Want to Play Sudoku Again
MIT 6.S095 Programming for the Puzzled, IAP 2018
View the complete course: https://ocw.mit.edu/6-S095IAP18
Instructor: Srini Devadas
Are Sudoku puzzles too difficult or tedious for you? Would you rather write a computer program that solves any Sudoku puzzle…
View the complete course: https://ocw.mit.edu/6-S095IAP18
Instructor: Srini Devadas
Are Sudoku puzzles too difficult or tedious for you? Would you rather write a computer program that solves any Sudoku puzzle…
День шестьдесят девятый. #CSharp8
Новые функции в C# 8.
1. Реализация по Умолчанию Интерфейсных Методов
Эта функция помогает вам добавлять функциональность к интерфейсам ваших библиотек, при этом поддерживая обратную совместимость с кодом, написанным для предыдущих версий этих интерфейсов.
Сейчас после того, как вы опубликовали интерфейс, «игра окончена». Вы не можете добавлять члены к интерфейсу без того, чтобы сломать все существующие его реализации.
C# 8.0 позволяет вам предоставить тело члена интерфейса. Поэтому, если кто-то не реализует этот член (возможно, потому что его ещё не существовало на момент написания кода), они просто будут использовать реализацию по умолчанию.
Преимущества
Вы можете добавлять функциональность к интерфейсам, не нарушая совместимость с предыдущими версиями этих интерфейсов.
Недостатки
Это нужно использовать с осторожностью. В противном случае можно легко нарушить принципы единственной ответственности. Подумайте, прежде чем использовать этот инструмент, нет ли другого, более элегантного решения вашей проблемы.
Источник: https://www.c-sharpcorner.com/article/c-sharp-8-features/
Новые функции в C# 8.
1. Реализация по Умолчанию Интерфейсных Методов
Эта функция помогает вам добавлять функциональность к интерфейсам ваших библиотек, при этом поддерживая обратную совместимость с кодом, написанным для предыдущих версий этих интерфейсов.
Сейчас после того, как вы опубликовали интерфейс, «игра окончена». Вы не можете добавлять члены к интерфейсу без того, чтобы сломать все существующие его реализации.
C# 8.0 позволяет вам предоставить тело члена интерфейса. Поэтому, если кто-то не реализует этот член (возможно, потому что его ещё не существовало на момент написания кода), они просто будут использовать реализацию по умолчанию.
interface ILoggerКласс
{
void Log(LogLevel level, string message);
// Новый перегруженный метод
void Log(Exception ex) => Log(LogLevel.Error, ex.ToString());
}
class ConsoleLogger : ILogger
{
public void Log(LogLevel level, string message) { ... }
// Метод Log(Exception) получает реализацию по умолчанию
}
ConsoleLogger
не имеет реализации перегруженного метода Log(Exception)
интерфейса ILogger
, поскольку был объявлен до внесения изменений в интерфейс. Теперь вы можете безопасно добавлять новые члены в существующие публичные интерфейсы, если вы предоставляете реализацию по умолчанию для уже существующих реализаторов.Преимущества
Вы можете добавлять функциональность к интерфейсам, не нарушая совместимость с предыдущими версиями этих интерфейсов.
Недостатки
Это нужно использовать с осторожностью. В противном случае можно легко нарушить принципы единственной ответственности. Подумайте, прежде чем использовать этот инструмент, нет ли другого, более элегантного решения вашей проблемы.
Источник: https://www.c-sharpcorner.com/article/c-sharp-8-features/
👍1
День семидесятый. #ЗаметкиНаПолях
For Или Foreach в C#
Многие программисты до сих пор путаются, когда использовать цикл
Внутри цикла
Дело в том,
Кроме того, в общем случае
Подводя итог, когда вам нужна простота чтения кода, используйте
Источник: https://www.c-sharpcorner.com/article/for-vs-foreach-in-c-sharp/
For Или Foreach в C#
Многие программисты до сих пор путаются, когда использовать цикл
for
, а когда foreach
. Рассмотрим перебор элементов коллекции в обоих циклах.List<Employee> employees = GetEmployeesList();Цикл for для списка будет выглядеть примерно так:
for (int i = 0; i < employees.Count; i++)Заметьте, что вы можете напрямую обращаться к элементам списка по индексу.
{
Console.WriteLine(employees[i].Age);
}
Внутри цикла
foreach
вы можете напрямую обращаться к каждому элементу: foreach(Employee emp in Employees)Заметьте, что цикл
{
Console.WriteLine(emp.Age);
}
foreach
создаёт копию коллекции, по которой вы проходите. Это означает, что, если вы хотите выполнить операцию присваивания на элементе коллекции, вы не сможете этого сделать:int[] numbers = { 1, 2, 3, 4, 5, 6 };Этот код приводит к ошибке
foreach (int item in numbers)
{
item++;
}
CS1656: Cannot assign to 'item' because it is a 'foreach iteration variable' (Невозможно выполнить присваивание переменной item, поскольку это ‘переменная итерации цикла foreach’)
.Дело в том,
item
здесь не ссылается на элемент массива, это просто временная переменная, и вы не можете присваивать ей значения.Кроме того, в общем случае
foreach
требует больше времени и дополнительную память, по сравнению с for
, поскольку использует методы GetEnumarator()
и Next()
интерфейса IEnumarable
.Подводя итог, когда вам нужна простота чтения кода, используйте
foreach
, когда требуется доступ к элементам внутри цикла, а также критична производительность, используйте for
. Источник: https://www.c-sharpcorner.com/article/for-vs-foreach-in-c-sharp/
День семьдесят первый. #CSharp8
Новые функции в C# 8.
2. Обнуляемый Ссылочный Тип
В C#8 можно объявлять обнуляемый контекст с помощью аннотации
Для необнуляемых ссылочных типов компилятор использует анализ потока, чтобы убедиться, что локальные переменные инициализированы не-
Обнуляемые ссылочные типы не проверяются на присваивание
Источник: https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-8
Новые функции в C# 8.
2. Обнуляемый Ссылочный Тип
В C#8 можно объявлять обнуляемый контекст с помощью аннотации
#nullable
. Внутри него любые переменные ссылочного типа считаются необнуляемыми. Если вы хотите присвоить ссылочному типу null
, нужно явно объявить обнуляемый тип переменной с помощью <тип>?
.Для необнуляемых ссылочных типов компилятор использует анализ потока, чтобы убедиться, что локальные переменные инициализированы не-
null
значением. Все поля должны быть инициализированы в конструкторе. Компилятор выдаёт предупреждение, если переменная не объявляется вызовом любого из доступных конструкторов или инициализатором.Обнуляемые ссылочные типы не проверяются на присваивание
null
, однако компилятор использует анализ потока, чтобы убедиться, что переменная обнуляемого типа не содержит null
, прежде чем к ней обращается код или она присваивается переменной необнуляемого типа.Источник: https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-8