Продвинутый уровень
Статья предоставляется как есть, может содержать неточную и неправильную информацию. Данный материал раскрывает больше возможностей работы с языком программирования которые не обязательны на начальном уровне владения.
Помогает упростить программирования в ряде случаев, например если нужно использовать однотипные задачи для различных типов данных. T - это универсальный параметр любого типа (можно использовать и другое имя).
Пример использования Id как числа или как серийного номера
Для установки значения по умолчанию используем default(T)
Вместо выражения x = x + 1 в некоторых языках можно использовать x += 1 или x++, что в принципе одно и тоже (см IL код) и зависит от стиля написания кода программистом или политики стиля написание кода в компании.
+=, -=, *=, ...
Это объект который указывает на метод(ы). Для определенного объекта можно назначать вызывать определенный метод или даже несколько в том числе в нескольких экземплярах.
null - это константа. Переменные ссылочного типа могут принимать значения null
?? - оператор null объединения, пример:
object a = null;
isNull = a ?? true;
var name = man?.Head?.Hair?.Color?.Name;
Для существующего типа добавляем новые методы без создания производного (наследуемого) класса без изменения основного, например если запрещено это делать.
Без определения класса и используя ключевое слово создаем анонимный тип со свойствами только для чтения. Можно использовать там где создание отдельного класса будет избыточным, например мы читаем из базы данных некоторую часть данных из таблицы. Пример:
Это функции определенные внутри других функции и имеет такой же внутренний доступ. Локальные функции могут быть только в единственном экземпляре, без перегрузок. Статический метод не дает доступ к переменным:
Без указания статического метода мы имеем доступ к переменным:
Применяются для того чтобы открыть или ограничить доступ. По умолчанию если не указан, то применяется модификатор private. Применяется к классам, полям, свойствам ...
Class по умолчанию имеет модификатор доступа internal, т.е. он доступен только внутри проекта/сборки. Для доступа в других проектах/сборках используется модификатор public, поэтому при написании кода пишем без него и добавляем этот модификатор, только при необходимости. При использовании модульных тестов удобно поставить модификатор public, но для правильных проектов лучше так не делать.
Уровень доступа у наследуемого класса должен быть не выше чем у базового.
public class C : A { } // public class C : A { } // Ошибка public class A { } class B{ }В синтаксисе языка C# используется
В некоторых языках можно использовать числа с разделителем нижнего подчеркивания. Например 10_0 это пример написания числа 100. Это удобно для написания больших чисел или для группировки.
Однажды написанный код должен максимально переиспользован.
Код должен быть очень простой и понятный, не нужно создавать дополнительного функционала или лишних настроек. Не нужно делать что-то сверх поставленной задачи. Не делайте избыточный функционал - например валидация поля для номера телефона если это не критично для автоматизации, например звонков. Не храните лишний код, удаляйте или выносите из проекта.
Разработка основанная на принципе что сначала разрабатывается тест, а потом реализуется функционал.
Принцип который решает устранение тяги программистов к избыточной абстракции, к экспериментам из интереса и к реализации избыточного функционала который сейчас не нужен. Это делается для того чтобы заказчик не оплачивал ненужный ему функционал а исполнитель не терял дополнительную прибыль
Для описания объекта используется класс, например с помощью его вы можете описать объект человека или автомобиля. А конкретный объект с которым вы взаимодействуете это экземпляр объекта. Для создания объекта используется:
Вид создания пользовательских типов данных, по аналогии с классами, только не нужно инициализировать. В структуре нельзя присваивать полям значение, необходимо присваивать вне или использовать конструктор и обязательно присваивать все поля. Члены структуры не могут быть защищены, потому что структура не может быть унаследована.
Описание
Установить значения поля по умолчанию при объявлении
Конструктор без параметров
Без определения конструкторов
Публичные, приватные модификаторы методов
Структура
⤫
⤫
✓
✓
Класс
✓
✓
✓
✓
Благодаря наследованию вы можете создать класс с базовый функциональностью или интерфейс для выбранного объекта. Например человек и два наследуемых объекта (мужчина и женщина) которые могут выполнять только строго свою функциональность (например анатомические возможности).
Базовый класс может быть простым, абстрактным или интерфейсом. Примеры:
Для наследования базового класса используется синтаксис через двоеточие
Для наследования интерфейса или нескольких используется синтаксис через двоеточие через запятую, но в данном случае это называется реализация.
При использовании ключевого слова virtual можно указать методу в базовом классе что его функциональность может быть переопределена, тогда в наследуемом классе можно использовать слово override для переопределения функции или свойства. Например хотим чтобы класс человека при передвижении иногда шел вприпрыжку вместо шага. Использование base позволяет выполнить код в базовом классе а использование слова override sealed позволяет запретить переопределение в последующих наследуемых классах.
При использовании ключевого слова new в наследуемом классе можно скрыть реализацию базового класса (код из базового класса выполнятся не будет). Например нам не нравится код в базовом классе, изменить который мы не можем и у него не установлен признак virtual. Доступ к базовой функциональности сохраняется при использовании ключевого слова base.
При указании ключевого слово abstract можно заложить некоторую функциональность, использование которого может быть только через другие наследуемые классы но не напрямую. Абстрактные методы в наследуемом классе должны быть реализованы. Удобно использовать когда требуется чтобы некоторая функциональность была реализована только в наследуемом классе.
Для класса можно указать один или несколько интерфейсов и соответственно все методы из этих интерфейсов должны быть реализованы, по аналогии тоже что требует и абстрактный класс при наследовании.
Используется для управляемого освобождения освобождения ресурсов. Реализация интерфейса IDisposable также позволяет освобождать ресурсы, а сочетание этих методов дает больше возможностей.
Преобразования из object должно делаться строго того типа которым и установлено.
object a = 1; // Число int32 string b = (string)a; // Ошибка преобразования из-за несовпадения типа int c = (int)a;Классы
Присваивание объекта производного типа к базовому типу выполнится присваивание ссылки, т.е. переменные firstMachine и automobile будут ссылаться на один и тот же объект в памяти, но доступ методам будет ограничен каждый своим определяемым классом. Соответственно при изменении данных в объекте в одной из переменной то данные в другой переменной того же объекта также будут изменены и таким образом например нельзя создать два разных объекта.
Присваивание экземпляра объекта к определенному типу делает создает его представление. Обратится к данным можно без присваивания при преобразовании:
Если преобразование будет неуспешно то значение будет установлено в null
Копирование объекта можно создание нового объекта вручную или автоматически с использованием MemberwiseClone (но будьте осторожны т.к. он копирует примитивные типы в том числе ссылки на объекты вместо самого объекта).
Для перехода выполнения кода к определенному участку используются метки. Пример выполнения бесконечного цикла.
В памяти эти две переменные будет храниться как одна строка и сравнение ссылки соответственно будет выполняться по тем же правилам. Подробнее почитать можно на habr.
При работе нескольких потоков в общими данными бывает необходимо ограничить непредсказуемый доступ на время выполнения кода, для этого используется конструкции вида lock, Monitor. Переменная X - должна быть ссылочного типа.
Позволяет сделать класс с новыми арифметическими возможностями
Пример
Для создания индексируемого объекта используется синтаксис как в свойствах с использованием ключевого свойства this. Тип индекса может быть не только числовым.
Явное (explicit) или неявное (implicit) преобразование типов при использовании ключевого слова operator можно выполнить преобразования из одного типа в другой (один ин них текущий тип).
У объекта с реализацией интерфейса IDisposable вызывается метод Dispose при завершении блока кода.
public class Machine: IDisposable { public string Name { get; set; }При использовании yield return возвращается значение, сохраняется текущее положение и при последующем вызове выполнение продолжается с того же места до следующего возврата yield return.
Альтернативный вариант
Использовать как
Нельзя использовать внутри try если есть catch (try-catch)
Есть ситуации когда компилятору можно сообщить какие участки пода программы должны или не должны быть скомпилированы. Для этого используется директивы и методы условной компиляции. Пример:
В блоке catch можно использовать фильтры:
Для создания исключения используется оператор throw
Или создаем класс
При использование throw в блоке catch исключение будет передано внешнему блоку
Тип enum по умолчанию типа int, для указания другого типа используется конструкция:
Используется любой числовой тип: byte, int, long, ulong, short, sbyte. Разные переменные могут иметь одинаковое значение, а также присваивание от других переменных
Использвание модификатора ref, out, in допустимо в любой последовательности. Модификатор in указывает что переменная только для чтения, модификатор out, то что переменную не нужно инициализировать