День сорок пятый. #TipsAndTricks
4. Добавление методов к перечислениям
Определить метод как часть перечислимого типа напрямую невозможно. Однако это ограничение можно обойти при помощи методов расширения. Рассмотрим упоминавшееся ранее перечисление дней недели (см. день сорок третий):
4. Добавление методов к перечислениям
Определить метод как часть перечислимого типа напрямую невозможно. Однако это ограничение можно обойти при помощи методов расширения. Рассмотрим упоминавшееся ранее перечисление дней недели (см. день сорок третий):
[Flags]Для добавления методов к перечислению нужно определить статический класс с методами расширения:
public enum Days
{
None = 0x0,
Sunday = 0x1,
Monday = 0x2,
Tuesday = 0x4,
Wednesday = 0x8,
Thursday = 0x10,
Friday = 0x20,
Saturday = 0x40
}
static class DaysExtensionsТеперь эти методы можно использовать, вызывая их из экземпляра перечисления:
{
static Days GetWorkdays(this Days days)
{
// 62 – сумма значений элементов от Monday до Friday
Enum.TryParse("62", true, out days);
return days;
}
public static Days GetWeekends(this Days days)
{
// 65 – сумма значений элементов Sunday и Saturday
Enum.TryParse("65", true, out days);
return days;
}
}
var d = Days.None;
Console.WriteLine("Рабочие дни: {0}", d.GetWorkdays());
Console.WriteLine("Выходные: {0}", d.GetWeekends());
// Вывод:
// Рабочие дни: Monday, Tuesday, Wednesday, Thursday, Friday
// Выходные: Sunday, Saturday
День сорок шестой. #ЗаметкиНаПолях
Кортежи
C# предоставляет богатый синтаксис классов и структур, который можно использовать для различных целей проектирования. Но иногда даже такой богатый синтаксис требует дополнительной работы, которая не приносит особой пользы. Вам может потребоваться написать метод, который использует простую структуру, содержащую более одного элемента данных. Для поддержки таких сценариев в язык C# были добавлены кортежи. Кортежи – это простые структуры данных, содержащие несколько полей. Поля не проверяются, и вы не можете определить ваши методы для кортежа.
До С# 7 кортежи были отдельным классом, и работать с ними было не так удобно. В 7й версии языка появился упрощённый синтаксис. Вы можете создать кортеж, присвоив значение каждому его члену:
- Справа от оператора присваивания:
Кортежи предоставляют упрощённый синтаксис для методов, возвращающих несколько дискретных значений. Вам не нужно создавать класс или структуру, определяющую возвращаемый тип. Создание кортежа более эффективно и более продуктивно. Пример ниже показывает метод, возвращающий максимальное и минимальное значения из последовательности целых чисел:
Источник: https://docs.microsoft.com/ru-ru/dotnet/csharp/whats-new/csharp-7#tuples
Кортежи
C# предоставляет богатый синтаксис классов и структур, который можно использовать для различных целей проектирования. Но иногда даже такой богатый синтаксис требует дополнительной работы, которая не приносит особой пользы. Вам может потребоваться написать метод, который использует простую структуру, содержащую более одного элемента данных. Для поддержки таких сценариев в язык C# были добавлены кортежи. Кортежи – это простые структуры данных, содержащие несколько полей. Поля не проверяются, и вы не можете определить ваши методы для кортежа.
До С# 7 кортежи были отдельным классом, и работать с ними было не так удобно. В 7й версии языка появился упрощённый синтаксис. Вы можете создать кортеж, присвоив значение каждому его члену:
var letters = ("a", "b");Обращаться к полям кортежа можно по именам
Item1
, Item2
и т.д. по порядку. Также им можно задать имена. Для этого есть два способа.- Справа от оператора присваивания:
var alphabetStart = (Alpha: "a", Beta: "b");- И слева от него:
(string Alpha, string Beta) namedLetters = ("a", "b");Задание имён и справа, и слева приведёт к предупреждению компилятора, и имена справа будут проигнорированы.
Кортежи предоставляют упрощённый синтаксис для методов, возвращающих несколько дискретных значений. Вам не нужно создавать класс или структуру, определяющую возвращаемый тип. Создание кортежа более эффективно и более продуктивно. Пример ниже показывает метод, возвращающий максимальное и минимальное значения из последовательности целых чисел:
private static (int Max, int Min) Range(IEnumerable<int> numbers)Объявление этого метода предоставляет имена полей возвращаемого кортежа. При вызове метода возвращаемым типом является кортеж, имена полей которого
{
int min = int.MaxValue;
int max = int.MinValue;
foreach(var n in numbers)
{
min = (n < min) ? n : min;
max = (n > max) ? n : max;
}
return (max, min);
}
Max
и Min
:var range = Range(numbers);Могут быть ситуации, когда вам нужно распаковать элементы кортежа, возвращённого из метода. Вы можете сделать это, объявив отдельные переменные для каждого из элементов кортежа. Это называется деконструкцией (разбором) кортежа:
Console.WriteLine(range.Min);
(int max, int min) = Range(numbers);PS: использовать новые функции кортежей можно и в более ранних версиях языка, подключив пакет
Console.WriteLine($"{min} - {max}");
System.ValueTuple
.Источник: https://docs.microsoft.com/ru-ru/dotnet/csharp/whats-new/csharp-7#tuples
👍1
День сорок седьмой. #ЗаметкиНаПолях
Приведение типов или Convert.To()
Несмотря на то, что эти операции могут казаться эквивалентными, они совершенно разные по целям.
Приведение типа – это действие по изменению объекта из одного типа данных в другой. Это достаточно общее определение, и в некотором смысле оно похоже на конвертацию, поскольку приведение типа часто имеет тот же синтаксис, что и конвертация. Поэтому возникает вопрос, когда достаточно приведения типа (неявного или явного), а когда вам придётся использовать более явную конвертацию.
Формально приведение типа изменит тип, тогда как конвертация изменит (или может изменить) значение (вместе с типом). Также приведение типа обратимо, тогда как конвертация может быть необратимой.
Неявные приведения типов
В C# приведение типа происходит неявно, когда вы не теряете информацию (заметьте, что эта проверка происходит на уровне типов, а не на уровне реальных значений переменных). Например, для примитивных типов:
Эти приведения неявны, поскольку при этом вы не теряете информацию (вы расширяете тип). В обратную сторону неявное приведение невозможно, потому что вне зависимости от реальных значений (они проверяются только во время выполнения) при приведении вы можете потерять часть данных. Например, следующий код не скомпилируется, потому что тип
Для объектов приведение типов всегда неявно, когда компилятор уверен, что исходный тип – производный класс от целевого или реализует целевой интерфейс, например:
В этих случаях информация не теряется, поскольку объекты не меняют своих типов, меняется только то, в каком типе вы их представляете.
Явные приведения типов
Приведение типа явно, когда оно не может быть выполнено неявно компилятором, и вам нужно использовать оператор приведения типа. Обычно это значит, что:
1. Вы можете потерять информацию или данные.
2. Преобразование может завершиться неудачей (поскольку вы не можете привести один тип к другому).
Явное преобразование подразумевает, что вы понимаете эти угрозы.
Для примитивных типов:
В обоих примерах, несмотря на то, что значения входят в диапазон типа
А следующее преобразование не скомпилируется, поскольку компилятор не умеет преобразовывать текст в число. Текст может содержать любые символы, не только цифры, поэтому в C# это недопустимо (хотя может быть допустимо в других языках):
Преобразования объектов могут завершиться неудачей, если типы несвязанные. Например, код ниже не скопмилируется:
Следующий код скомпилируется, но он может привести к ошибке времени выполнения
Приведение типов или Convert.To()
Несмотря на то, что эти операции могут казаться эквивалентными, они совершенно разные по целям.
Приведение типа – это действие по изменению объекта из одного типа данных в другой. Это достаточно общее определение, и в некотором смысле оно похоже на конвертацию, поскольку приведение типа часто имеет тот же синтаксис, что и конвертация. Поэтому возникает вопрос, когда достаточно приведения типа (неявного или явного), а когда вам придётся использовать более явную конвертацию.
Формально приведение типа изменит тип, тогда как конвертация изменит (или может изменить) значение (вместе с типом). Также приведение типа обратимо, тогда как конвертация может быть необратимой.
Неявные приведения типов
В C# приведение типа происходит неявно, когда вы не теряете информацию (заметьте, что эта проверка происходит на уровне типов, а не на уровне реальных значений переменных). Например, для примитивных типов:
int tinyInteger = 10;
long bigInteger = tinyInteger;
float tinyReal = 10.0f;
double bigReal = tinyReal;
Эти приведения неявны, поскольку при этом вы не теряете информацию (вы расширяете тип). В обратную сторону неявное приведение невозможно, потому что вне зависимости от реальных значений (они проверяются только во время выполнения) при приведении вы можете потерять часть данных. Например, следующий код не скомпилируется, потому что тип
double
может содержать значения, не представленные в типе float
:double bigReal = Double.MaxValue;
float tinyReal = bigReal;
Для объектов приведение типов всегда неявно, когда компилятор уверен, что исходный тип – производный класс от целевого или реализует целевой интерфейс, например:
string text = "123";
IFormattable formattable = text;
NotSupportedException derivedException = new NotSupportedException();
Exception baseException = derivedException;
В этих случаях информация не теряется, поскольку объекты не меняют своих типов, меняется только то, в каком типе вы их представляете.
Явные приведения типов
Приведение типа явно, когда оно не может быть выполнено неявно компилятором, и вам нужно использовать оператор приведения типа. Обычно это значит, что:
1. Вы можете потерять информацию или данные.
2. Преобразование может завершиться неудачей (поскольку вы не можете привести один тип к другому).
Явное преобразование подразумевает, что вы понимаете эти угрозы.
Для примитивных типов:
double precise = Math.Cos(Math.PI * 1.23456) / Math.Sin(1.23456);
float coarse = (float)precise;
float epsilon = (float)Double.Epsilon;
В обоих примерах, несмотря на то, что значения входят в диапазон типа
float
, вы теряете информацию (точность), поэтому преобразование должно быть явным. А такое приведение завершится неудачей:float max = (float)Double.MaxValue;
А следующее преобразование не скомпилируется, поскольку компилятор не умеет преобразовывать текст в число. Текст может содержать любые символы, не только цифры, поэтому в C# это недопустимо (хотя может быть допустимо в других языках):
string text = "123";
double value = (double)text;
Преобразования объектов могут завершиться неудачей, если типы несвязанные. Например, код ниже не скопмилируется:
string text = (string)AppDomain.Current;
Exception exception = (Exception)"abc";
Следующий код скомпилируется, но он может привести к ошибке времени выполнения
InvalidCastException
в зависимости от реального типа объекта:object obj = GetNextObjectFromInput();
string text = (string)obj;
Exception exception = (Exception)obj;
Преобразования
Поэтому, отбрасывая некоторые незначительные нюансы реализации типа
Convert
или интерфейса IConvertible
, в случае приведения типа в C# вы говорите компилятору:«Доверься мне, этот тип можно привести к этому типу. Даже если ты этого не знаешь сейчас, позволь мне это сделать и всё получится.»
или
«Не беспокойся, мне неважно, если что-то потеряется при приведении.»
Для любого другого приведения, когда требуется более явная операция, требуется преобразование значения. Например, для приведения из
string
в double
может потребоваться парсинг. Преобразование в строку, например, всегда возможно, (через метод ToString()
), хотя может означать что-то другое, нежели то, что вы ожидаете.Такие преобразования могут выполняться изнутри объекта, используя методы преобразования, либо с помощью более сложных механизмов (
TypeConverter
). Вы не знаете, что может случиться во время преобразования, поэтому, по моему мнению, когда более строгое преобразование доступно, вы должны его использовать.Подводя итог, когда можно использовать явное приведение типов:
1. Приведение между базовыми типами.
2. Приведение от объекта в другой тип (может включать распаковку).
3. Приведение от производного в базовый класс (или в реализованный интерфейс).
4. Преобразование из одного типа к другому через специальные операторы преобразования.
Только первый из этих вариантов может быть реализован через тип
Convert
. Для остальных случаев у вас нет другого выбора, кроме явного приведения типа.Когда можно использовать тип
Convert
:1. Преобразование из одного базового типа в другой (с некоторыми ограничениями).
2. Преобразование из типа, реализующего интерфейс
IConvertible
в любой другой (поддерживаемый) тип.3. Преобразования массива битов в строку и наоборот.
Заключение
По моему мнению,
Convert
должен использоваться во всех случаях, когда вы знаете, что преобразование может завершиться неудачей, даже если оно может быть выполнено с помощью приведения типов. Это даёт понять читающим ваш код ваши намерения и что вы знаете, что преобразование может завершиться неудачей. Для остальных случаев используйте приведение типа, т.к. нет выбора. Но если доступен другой метод (Parse
, TryParse
), я советую его использовать. Кроме того, имейте в виду, что приведение типов и
Convert
иногда приводят к разным результатам. Например: double real = 1.6;
int castedInteger = (int)real; // 1
int convertedInteger = Convert.ToInt32(real); // 2
Приведение типа (ожидаемо) отсекает дробную часть, а Convert осуществляет округление до ближайшего целого (а это может стать неожиданностью). Каждое преобразование может отличаться от приведения типа, поэтому единого правила для всех случаев нет. Лучше для каждого случая проконсультироваться с MSDN.
Источник: https://stackoverflow.com/questions/15394032/difference-between-casting-and-using-the-convert-to-method
👍1
День сорок восьмой. #TipsAndTricks
5. IntelliCode для Visual Studio
IntelliCode сохраняет ваше время, выбирая в качестве подсказки для автозаполнения то, что вы скорее всего будете использовать. Рекомендации IntelliCode основаны на тысячах проектов с открытым кодом на GitHub. При сочетании с контекстом вашего кода список подсказок теперь нацелен на наиболее используемые варианты. В результате вместо того, чтобы искать и прокручивать отсортированный список, вы получаете предложения наиболее вероятных вариантов в самом начале, как только начинаете печатать. При вводе члена класса вы заметите рекомендации IntelliCode, отмеченные звёздочкой (см. рисунок). Скачайте IntelliCode для VisualStudio здесь: https://marketplace.visualstudio.com/items?itemName=VisualStudioExptTeam.VSIntelliCode
Источник: https://devblogs.microsoft.com/visualstudio/argument-completion-made-easy-with-visual-studio-intellicode/
5. IntelliCode для Visual Studio
IntelliCode сохраняет ваше время, выбирая в качестве подсказки для автозаполнения то, что вы скорее всего будете использовать. Рекомендации IntelliCode основаны на тысячах проектов с открытым кодом на GitHub. При сочетании с контекстом вашего кода список подсказок теперь нацелен на наиболее используемые варианты. В результате вместо того, чтобы искать и прокручивать отсортированный список, вы получаете предложения наиболее вероятных вариантов в самом начале, как только начинаете печатать. При вводе члена класса вы заметите рекомендации IntelliCode, отмеченные звёздочкой (см. рисунок). Скачайте IntelliCode для VisualStudio здесь: https://marketplace.visualstudio.com/items?itemName=VisualStudioExptTeam.VSIntelliCode
Источник: https://devblogs.microsoft.com/visualstudio/argument-completion-made-easy-with-visual-studio-intellicode/
День сорок девятый. #ЗаметкиНаПолях
Деконструкция
Начиная с C# 7.0, вы можете извлекать несколько элементов из кортежа или несколько значений полей, свойств из объекта в одной операции деконструкции. При этом вы присваиваете значения полей кортежа или членов объекта отдельным переменным.
Деконструкция кортежа
Синтаксис деконструкции кортежа похож на синтаксис его определения (см. день сорок шестой). Допустим, есть метод
Есть три варианта деконструкции:
1. Явно определить типы переменных
Кроме этого, вы можете использовать уже ранее объявленные переменные:
- вы не можете объявить определённый тип вне скобок, даже если все поля кортежа одного типа;
- вы обязаны присвоить каждое поле массива переменной;
- вы не можете смешивать объявления переменных с использованием ранее объявленных переменных.
Если значения каких-либо полей кортежа вам не нужны, вы можете использовать специальный символ пустой переменной "
Некортежные типы не предлагают встроенной поддержки деконструкции. Но автор класса, структуры или интерфейса может позволить производить деконструкцию экземпляров класса, реализовав метод
При деконструкции экземпляров, так же, как и для кортежей, можно использовать пустые переменные.
Если вы не являетесь автором класса, вы можете производить деконструкцию экземпляров этого класса, реализовав один или несколько методов
Источник: https://docs.microsoft.com/ru-ru/dotnet/csharp/deconstruct
Деконструкция
Начиная с C# 7.0, вы можете извлекать несколько элементов из кортежа или несколько значений полей, свойств из объекта в одной операции деконструкции. При этом вы присваиваете значения полей кортежа или членов объекта отдельным переменным.
Деконструкция кортежа
Синтаксис деконструкции кортежа похож на синтаксис его определения (см. день сорок шестой). Допустим, есть метод
QueryCityData
, возвращающий для заданного города название, численность населения и площадь города.Есть три варианта деконструкции:
1. Явно определить типы переменных
(string city, int population, double area) = QueryCityData("New York City");2. Использовать ключевое слово
var
вне скобок для всех переменных:var (city, population, area) = QueryCityData("New York City");3. Использовать
var
любой или всех переменных:(string city, var population, var area) = QueryCityData("New York City");Этот метод использовать не рекомендуется.
Кроме этого, вы можете использовать уже ранее объявленные переменные:
string city = "Raleigh";Заметьте:
int population = 458880;
double area = 144.8;
(city, population, area) = QueryCityData("New York City");
- вы не можете объявить определённый тип вне скобок, даже если все поля кортежа одного типа;
- вы обязаны присвоить каждое поле массива переменной;
- вы не можете смешивать объявления переменных с использованием ранее объявленных переменных.
Если значения каких-либо полей кортежа вам не нужны, вы можете использовать специальный символ пустой переменной "
_
". Например, если из примера выше нам нужно получить только население города:var (_, population, _) = QueryCityData("New York City");Деконструкция пользовательских типов
Некортежные типы не предлагают встроенной поддержки деконструкции. Но автор класса, структуры или интерфейса может позволить производить деконструкцию экземпляров класса, реализовав метод
Deconstruct
. Метод должен возвращать void
, а каждое значение для деконструкции должно быть обозначено ключевым словом out
. Например, следующий метод Deconstruct
класса Person
возвращает имя, отчество и фамилию:public void Deconstruct(out string fname, out string mname, out string lname)Произвести деконструкцию экземпляра класса
Person
, присвоенного переменной p
, можно следующим образом:var (fName, mName, lName) = p;Можно перегружать методы
Deconstruct
для вызова разного количества и разных комбинаций свойств. Однако, нужно быть осторожным, определяя методы Deconstruct
, с уникальными и однозначными сигнатурами. Несколько методов Deconstruct
, имеющие одинаковое количество параметров, но разные типы или разный порядок параметров допустимы, но могут приводить к путанице.При деконструкции экземпляров, так же, как и для кортежей, можно использовать пустые переменные.
Если вы не являетесь автором класса, вы можете производить деконструкцию экземпляров этого класса, реализовав один или несколько методов
Deconstruct
в качестве методов расширения.Источник: https://docs.microsoft.com/ru-ru/dotnet/csharp/deconstruct
👍1
День пятидесятый. #ЗаметкиНаПолях
Управление цепочками делегатов
В C# можно создавать и управлять цепочками делегатов при помощи операторов
В качестве альтернативы можно использовать метод
Управление цепочками делегатов
В C# можно создавать и управлять цепочками делегатов при помощи операторов
+=
и -=
. Цепочку делегатов можно вызвать так же, как и единичный делегат. При этом будут вызваны все делегаты цепочки по очереди. Это достаточно удобно и подходит для большинства сценариев. Однако у этого метода есть ряд ограничений. Например, сохраняется только последнее из возвращаемых значений, возвращаемых методами. Получить остальные значения нельзя. Кроме того, если один из делегатов в цепочке выбрасывает исключение, работа цепочки останавливается.В качестве альтернативы можно использовать метод
GetInvokationList
класса MulticastDelegate
. Он возвращает массив ссылок на делегаты в цепочке. Следующий код безопасно выполняет делегаты из цепочки и сохраняет их возвращаемые значения:private delegate string MyDelegate();Источник: Джеффри Рихтер “CLR via C#”. 3-е изд. – СПб.: Питер, 2012. Глава 17.
private static string Method1() => "Method1";
private static string Method2() => throw new Exception("Exception");
private static string Method3() => "Method3";
static void Main(string[] args)
{
MyDelegate getResult = null;
getResult += new MyDelegate(Method1);
getResult += new MyDelegate(Method2);
getResult += new MyDelegate(Method3);
Console.WriteLine(GetAllResults(getResult));
}
private static string GetAllResults(MyDelegate result)
{
if (result == null) return null;
var report = new StringBuilder();
var delegates = result.GetInvocationList();
foreach (MyDelegate del in delegates)
{
try
{
//пытаемся выполнить метод, сохраняя его результат
report.AppendFormat("{0}\n", del());
}
catch (Exception ex)
{
//обрабатываем ошибки метода
//здесь component – класс владелец метода
var component = del.Target;
report.AppendFormat(
" Ошибка при получении результата из метода {0}{1}: {2}\n",
((component == null) ? "" : component.GetType() + "."),
del.Method.Name,
ex.Message);
}
}
return report.ToString();
}
День пятьдесят первый. #TipsAndTricks
Обучение IntelliCode
Недавно я рассказывал, как IntelliCode помогает вам писать код, выбирая наиболее подходящие подсказки на основе тысяч часто используемых библиотек в репозиториях GitHub. Вместо поиска и прокрутки отсортированного списка методов и свойств, вы получаете наиболее вероятные подсказки на основе вашего контекста программы.
Но что, если вы хотите получать такие подсказки на основе вашего набора библиотек? В C# вы можете позволить IntelliCode анализировать ваш собственный код и делиться результатами анализа внутри вашей команды. Установить зависимость IntelliCode от вашего кода, проанализировать его и поделиться результатами анализа с коллегами можно в течение нескольких минут. Это можно сделать в 3 простых шага:
1. Убедитесь, что у вас установлено расширение IntelliCode для
Visual Studio.
2. Создайте вашу модель кодовой базы, содержащую хорошие примеры использования желаемых библиотек классов. Помните, что качество подсказок, предлагаемых IntelliCode напрямую зависит от качества примеров, которые вы предоставите.
3. Поделитесь моделью с вашими коллегами, чтобы они смогли использовать рекомендации. Если вам потребуется обновить модель, например, после внесения существенных изменений в код, ваша команда автоматически получит последние изменения.
Подробности тут: https://docs.microsoft.com/en-us/visualstudio/intellicode/faq
Источник: https://devblogs.microsoft.com/visualstudio/code-more-scroll-less-with-visual-studio-intellicode/?utm_source=vs_developer_news&utm_medium=referral
Обучение IntelliCode
Недавно я рассказывал, как IntelliCode помогает вам писать код, выбирая наиболее подходящие подсказки на основе тысяч часто используемых библиотек в репозиториях GitHub. Вместо поиска и прокрутки отсортированного списка методов и свойств, вы получаете наиболее вероятные подсказки на основе вашего контекста программы.
Но что, если вы хотите получать такие подсказки на основе вашего набора библиотек? В C# вы можете позволить IntelliCode анализировать ваш собственный код и делиться результатами анализа внутри вашей команды. Установить зависимость IntelliCode от вашего кода, проанализировать его и поделиться результатами анализа с коллегами можно в течение нескольких минут. Это можно сделать в 3 простых шага:
1. Убедитесь, что у вас установлено расширение IntelliCode для
Visual Studio.
2. Создайте вашу модель кодовой базы, содержащую хорошие примеры использования желаемых библиотек классов. Помните, что качество подсказок, предлагаемых IntelliCode напрямую зависит от качества примеров, которые вы предоставите.
3. Поделитесь моделью с вашими коллегами, чтобы они смогли использовать рекомендации. Если вам потребуется обновить модель, например, после внесения существенных изменений в код, ваша команда автоматически получит последние изменения.
Подробности тут: https://docs.microsoft.com/en-us/visualstudio/intellicode/faq
Источник: https://devblogs.microsoft.com/visualstudio/code-more-scroll-less-with-visual-studio-intellicode/?utm_source=vs_developer_news&utm_medium=referral
Docs
Frequently asked questions - Visual Studio IntelliCode
День пятьдесят второй.
Сертификат Microsoft. Шаг 2
Поискал информацию о сдаче экзамена 70-483 «Programming in C#». Интересен был опыт людей, прошедших через это. На удивление статей не так много:
- Хабр https://habr.com/ru/post/245067/ (пятилетней давности).
- Блог на BlogSpot https://sonyks2007.blogspot.com/2014/02/mcp.html (пятилетней давности).
- Блог Андрея Акиньшина https://aakinshin.net/ru/posts/ms-mcp/ (пятилетней давности).
- Блог Дмитрия Маслова https://dmaslov.net/2018/09/06/exam-70-483/ (прошлогодний).
Остальное откровенный шлак, нисколько не полезный.
Что хочется отметить:
1. Авторы не раскрывают вопросов от слова совсем. На это ты подписываешь соглашение о неразглашении перед экзаменом.
2. Темы варьируются. Например, интересно было узнать, что в экзамен входят вопросы по шифрованию данных и управлению сборками. Не помню этих тем в списке на оф. сайте экзамена.
3. Книги по подготовке:
- Wouter de Kort, Exam Ref 70-483: Programming in C#
- Tiberiu Covaci, MCSD Certification Toolkit (Exam 70-483): Programming in C# (Wrox Programmer to Programmer)
Несколько человек написали, что не стоят своих денег, и если первая ещё более менее, то вторая содержит дикое количество ошибок и на неё вообще не стоит тратить время.
4. Варианты вопросов всё-таки есть вот на этом сайте: https://exambraindumps.com/70-483.html Там же можно сдать пробный экзамен. Не знаю, насколько легально это там размещено. Вопросы, говорят, что тоже не без ошибок. Посмотрим. Нужно выделить 1,5 часа на пробный тест.
Продолжаем подготовку…
PS: Хотел узнать, где поблизости можно пройти экзамен, т.к. из авторов один сдавал в Киеве, другой в Екатеринбурге, но кнопка "Запланировать экзамен" на сайте экзамена почему-то ведёт на пустую страницу.
Сертификат Microsoft. Шаг 2
Поискал информацию о сдаче экзамена 70-483 «Programming in C#». Интересен был опыт людей, прошедших через это. На удивление статей не так много:
- Хабр https://habr.com/ru/post/245067/ (пятилетней давности).
- Блог на BlogSpot https://sonyks2007.blogspot.com/2014/02/mcp.html (пятилетней давности).
- Блог Андрея Акиньшина https://aakinshin.net/ru/posts/ms-mcp/ (пятилетней давности).
- Блог Дмитрия Маслова https://dmaslov.net/2018/09/06/exam-70-483/ (прошлогодний).
Остальное откровенный шлак, нисколько не полезный.
Что хочется отметить:
1. Авторы не раскрывают вопросов от слова совсем. На это ты подписываешь соглашение о неразглашении перед экзаменом.
2. Темы варьируются. Например, интересно было узнать, что в экзамен входят вопросы по шифрованию данных и управлению сборками. Не помню этих тем в списке на оф. сайте экзамена.
3. Книги по подготовке:
- Wouter de Kort, Exam Ref 70-483: Programming in C#
- Tiberiu Covaci, MCSD Certification Toolkit (Exam 70-483): Programming in C# (Wrox Programmer to Programmer)
Несколько человек написали, что не стоят своих денег, и если первая ещё более менее, то вторая содержит дикое количество ошибок и на неё вообще не стоит тратить время.
4. Варианты вопросов всё-таки есть вот на этом сайте: https://exambraindumps.com/70-483.html Там же можно сдать пробный экзамен. Не знаю, насколько легально это там размещено. Вопросы, говорят, что тоже не без ошибок. Посмотрим. Нужно выделить 1,5 часа на пробный тест.
Продолжаем подготовку…
PS: Хотел узнать, где поблизости можно пройти экзамен, т.к. из авторов один сдавал в Киеве, другой в Екатеринбурге, но кнопка "Запланировать экзамен" на сайте экзамена почему-то ведёт на пустую страницу.
День пятьдесят третий. #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/