Р АЗРАБОТКА ПРИЛОЖЕНИЙ НА ПЛАТФОРМЕ.NET Лекция 2 Объектно-ориентированное программирование.

Презентация:



Advertisements
Похожие презентации
Наследование Наследование – это отношение является между классами. class Person { string first_name; int birth_year;... } class Student : Person { float.
Advertisements

Перегрузка операторов x = a + b результат 1-й операнд2-й операнд оператор По количеству операндов операторы делятся на: унарные (один операнд) бинарные.
Классы в С#. Перечисления С# Перечисление задает конечное множество возможных значений, которые могут получать объекты класса перечисление. [атрибуты][модификаторы]
Учебный курс Объектно-ориентированный анализ и программирование Лекция 7 Методы как средство реализации операций Лекции читает кандидат технических наук.
Полиморфизм. Полиморфизм – это свойство системы использовать объекты с одинаковым интерфейсом без информации о типе и внутренней структуре объекта.
Основы информатики Классы Заикин Олег Сергеевич zaikin.all24.org
ОБЪЕКТНО- ОРИЕНТИРОВАННОЕ ПРОГРАММИРОВАНИЕ (ООП) 1.
Наследование и полиморфизм. «Быть» или «Иметь» а так же «Точно» или «Как получится»
1 ©Павловская Т.А. (СПбГУ ИТМО) Курс «С#. Программирование на языке высокого уровня» Павловская Т.А.
Интерфейсы Лекция 4. Реализуйте очередь в виде списка, содержащую комплексные числа Реализуйте методы void Enqueue(Complex с ) – помещает число в очередь.
Наследование Полиморфизм ВЫЗОВ КОНСТРУКТОРОВ И ДЕСТРУКТОРОВ ПРИ НАСЛЕДОВАНИИ.
©Павловская Т.А. (СПбГУ ИТМО) Курс «С#. Программирование на языке высокого уровня» Павловская Т.А.
Основы ООП и C# Работа с объектами и классами. Классы Класс специальный тип данных для описания объектов. Он определяет данные и поведение типа. Определение.
С# и ООП Формальное определение класса с C# Класс в C# - это пользовательский тип данных (user defined type), который состоит из данных (часто называемых.
Обобщения ( generics) Обобщения – это классы, структуры, интерфейсы и методы, в которых некоторые типы сами являются параметрами. Эти типы перечисляются.
Высокоуровневые методы информатики и программирования Лекция 14 Интерфейсы.
Интерфейсы Обобщения ( шаблоны ) Лекция 4. Интерфейсы Обобщения.
.NET framework Колотаев А.В.
Объектно-ориентированное программирование С++. Лекция 6 Карпов В.Э.
Лекция 4. Введение в С++ Наследование, множественное наследование. Конструкторы, деструкторы. Виртуальные функции.
Транксрипт:

Р АЗРАБОТКА ПРИЛОЖЕНИЙ НА ПЛАТФОРМЕ.NET Лекция 2 Объектно-ориентированное программирование

С ЕГОДНЯ Основы ООП Введение Пример класса Основные принципы ООП Наследование в C# Особенности ООП в С# Тип object Преобразование типов Полиморфизм в C# virtual, override, new, abstract class, abstract method Инкапсуляция в C# Члены класса (и структуры) Дополнительный сведения о структурах и классах

О СНОВЫ ОБЪЕКТНО - ОРИЕНТИРОВАННОГО ПРОГРАММИРОВАНИЯ

Э ВОЛЮЦИЯ Линейный код. Макросы – повторное использование кода (копируются в указанное место) Подпрограммы – повторное использование кода, абстрагирование от основной программы Модули (в понимании С). Объекты. Совокупность данных, способов преобразования данных, операции с данными

К ЛАСС И ЭКЗЕМПЛЯР КЛАССА Члены класса Поле – содержит данные Метод – выполнят действия (над данными) Свойство (С#) – виртуальное поле (совокупность методов get и set) Конструктор – метод, автоматически вызываемый при создании объекта Деструктор – метод, автоматически вызываемы при удалении объекта Константы Тип (класс) Члены класса Объект – это экземпляр класса (типа)

К ЛАСС. О БЪЯВЛЕНИЕ В С# [attributes] [modifiers] class class_name [: [base_class] [interfaces] ] { [class_member1] … [class_memberN] }

П РИМЕР КЛАССА public class Пиво : Выпивка { public Пиво (string сорт, float градус) { this.сорт = сорт; this.градус = градус; } public void Выпить() { Console.WriteLine(Ух ты! + сорт + – жжотъ!!!); } public string Сорт { get {return сорт;} } public float Градус {get {return градус;} } protected readonly string сорт; protected float градус; }

Д ЕМОНСТРАЦИЯ класс Пиво

О СНОВНЫЕ ПРИНЦИПЫ ООП Инкапсуляция Сокрытие реализации. Отделение интерфейса от реализации. Работа с данными только через методы Например: string s = Console.ReadLine() Наследование Расширение функциональности базового класса в производном (дочернем) классе Многократное использование кода Полиморфизм Сопоставление одному имени нескольких сущностей Одно имя – несколько реализаций

О СОБЕННОСТИ НАСЛЕДОВАНИЯ В C# Запрещено множественное наследование. Если необходимо унаследовать от множества типов, можно использовать принцип has a и делегировать необходимые методы вложенного типа. Делегирование. Нет модификаторов наследования. Наследование всегда public. Базовый и производный класс могут быть написаны на разных языках Наследование структур запрещено.

Н АСЛЕДОВАНИЕ Отношение is a – является. Отношение has a – содержит. ранг, операции Традиционное наследование Делегирование

С ИНТАКСИС НАСЛЕДОВАНИЯ [Атрибуты] [Модификаторы] class ИмяПроизводногоКласса : ИмяБазовогоКласса { Тело класса } Базовый (родительский) класс – тот класс, от которого наследуют Производный класс – тот, который наследует Базовый и производный класс могут быть написаны на разных языках class Matrix { public int Rang() {... }; } class DiagMatrix : Matrix { public bool isE() {... }; DiagMatrix dm = new DiagMatrix(); int i = dm.Rang();

Р ЕАЛИЗАЦИЯ ПРИНЦИПА HAS A public class Radio { public void Power(bool turnOn) { Console.WriteLine("Радио {0}", (turnOn)? "включено" : "выключено"); } public class Car { private Radio myRadio = new Radio(); public void TurnRaduionOnOff(bool OnOff) { myRadio.Power(OnOff); } Делегирование

И ЕРАРХИЯ КЛАССОВ С++ - ациклический ориентированные граф С# - дерево Корнем дерева в С# служит тип System.Object или сокращенно просто object

М ЕТОДЫ S YSTEM.O BJECT string ToString() Позволяет получить строковое представление объекта По умолчанию возвращает квалифицированное имя типа int GetHashCode() Позволяет получать хэш-код объекта bool Equals(object o) Позволяет сравнивать любые объекты Для ссылочных типов по умолчанию сравнение на равенство ссылок Для типов значения по умолчанию сравнение значений Type GetType () Переопределяйте, если семантика по умолчанию неприемлема (кроме GetType() )

С ТАТИЧЕСКИЙ И ДИНАМИЧЕСКИЙ ТИП Переменная базового класса может ссылаться на объект производного класса Статический тип – тип переменной. Динамический тип – реальный тип объекта, на который переменная указывает. Пример: Control ctrl = new Button(OK); Статический тип – Control Динамический тип - Button

М ЕТОД O BJECT.G ET T YPE () Метод GetType() возвращает объект типа System.Type Возвращаемый объект соответствует динамическому типу объекта Метод GetType() нельзя переопределить На этом держится вся типобезопасность (type safety) в.NET

Н ЕКОТОРЫЕ С ПЕЦИАЛЬНЫЕ БАЗОВЫЕ ТИПЫ System.Array : object базовый класс для всех массивов System.ValueType : object базовый класс для всех типов-значений System.Enum : System.ValueType базовый класс для всех перечислений System.Exception : object базовый класс для всех исключений System.Delegate : object базовый класс для всех делегатов

П РЕОБРАЗОВАНИЯ ТИПОВ Ссылка на производный класс неявно приводится к ссылке на базовый класс Control ctrl = new Button(OK); Ссылка на базовый класс может быть явно приведена к ссылке на производный класс Button button = (Button)ctrl; Если подобное преобразование недействительно, то выбрасывается исключение Функция, принимающая базовый класс в качестве параметра, может принять и его производный класс void Show(Control ctrl){…} Show(button);

П РЕОБРАЗОВАНИЕ ТИПОВ Обычный синтаксис: (Имя_типа) выражение Если преобразование не проходит, то вызывается исключение Button button = (Button)ctrl; Оператор as expression as Имя_типа Если преобразование не проходит, то возвращается null Применимо только к ссылочным типам Button button = ctrl as Button;

О ПЕРАТОР IS Оператор is проверяет, имеет ли выражение заданный тип выражение is Имя_типа Оператор возвращает true, если Выражение не есть null Преобразование выражения в заданный тип проходит Пример if(number is int) { int i = (int)number; … } else if(number is double) { double d = (double)number; … }

О ПЕРАТОР TYPEOF Служит для получения объекта System.Type для заданного типа typeof(Имя_Типа) Пример if(number.GetType() == typeof(int)) { … } else if(number.GetType() == typeof(doudle)) { … } Можно использовать для точной проверки динамического типа

П РИВЕДЕНИЕ ТИПОВ - ЗНАЧЕНИЙ К OBJECT Используются упаковка (boxing) и распаковка (unboxing) boxing : в куче создается специальный объект, в который упаковывается объект- значение int j = 5; object obj = j; unboxing : значение извлекается из этого объекта int k = (int)obj; При упаковке и распаковке создаются новые объекты Избегайте частых преобразований boxing/ unboxing. Вызывается также при использовании методов типа object. Например, ToString()

С ПЕЦИАЛЬНЫЕ ПРЕОБРАЗОВАНИЯ НЕКОТОРЫХ ТИПОВ Преобразование типа string к типам int, long, short, double и т.п.: Имя_типа.Parse (string) Например: int i = int.Parse("5"); Безопасное преобразование: bool Имя_типа.TryParse (string, out Имя_переменной ) Например: int i; if (int.TryParse("52", out i)) { /*Используем i*/ }; Преобразование различных типов значимые типы: Convert.ToXXX(object) Например: int i = Convert.ToInt32('5'); Преобразование к строке: метод ToString() Например: int i = 5; string s = i.ToString();

Н АСЛЕДОВАНИЕ Добавление новой функциональности Объявление новых членов class Matrix { public int Rang() {... }; } class DiagMatrix : Matrix { public bool isE() {... }; … DiagMatrix dm = new DiagMatrix(); int i = dm.Rang(); bool b = dm.isE(); Изменение базовой функциональности Перекрытие базовых членов Переопределение (overriding) базовых методов Полиморфизм

П ОЛИМОРФИЗМ Использование связанных объектов одинаковым образом class Shape { // Рисует фигуру public virtual void Draw() { } } class Circle : Shape { // Рисует окружность public override void Draw() { } } class Hexagon : Shape { // Рисует многоугольник public override void Draw() { } }

П ОЛИМОРФИЗМ Динамический полиморфизм Виртуальные члены Абстрактные члены Статический полиморфизм Перегрузка функций Перегрузка операций Сокрытие (hiding) членов

В ИРТУАЛЬНЫЕ ЧЛЕНЫ Виртуальные члены позволяют обеспечивать различные реализации class Shape {public virtual void Draw() { }} class Circle : Shape {public override void Draw() { }} class Hexagon : Shape{public override void Draw() { }} Виртуальные члены обеспечивают связывание на основе динамического типа Shape sh1 = new Circle(); sh1.Draw() Shape sh2 = new Shape(); sh2.Draw() Shape sh3 = new Hexagon(); sh3.Draw() Виртуальные члены позволяют изменять функциональность базового класса Виртуальные методы должны иметь одну и ту же сигнатуру

О БЪЯВЛЕНИЕ ВИРТУАЛЬНЫХ ЧЛЕНОВ При объявлении используется модификатор virtual Виртуальные члены не могут быть статическими или закрытыми Примеры виртуальных членов public virtual int Method(); public virtual double Property {…} protected virtual void OnPaint();

П ЕРЕКРЫТИЕ ВИРТУАЛЬНЫХ ЧЛЕНОВ Для перекрытия виртуальных членов используется модификатор override Специальный модификатор необходим для лучшей поддержки IDE Примеры перекрытия: public override string ToString(); protected override void Draw();

С ОКРЫТИЕ ЧЛЕНОВ Член (не метод и не индексатор) скрывает все члены с тем же именем в базовом классе class Shape { int Square;} class Circle : Shape { double Square; } Метод скрывает все члены с тем же именем и методы с той же сигнатурой в базовом классе Необходимо указывать new или override. По- умолчанию new. Индексатор скрывает индексатор с той же сигнатурой в базовом классе Сокрытие распространяется вниз по иерархии

М ОДИФИКАТОР NEW Если случается сокрытие членов, компилятор выдает предупреждение Чтобы избежать этого, используйте модификатор new new помогает разрешить проблемы с версиями Сокрытие с new распространяется вниз по иерархии

П РИМЕР class Program { static void Main(string[] args) { Shape sh = new Shape(); Console.WriteLine(sh.ShapeName()); sh = new Hexagon(); Console.WriteLine(sh.ShapeName()); sh = new Square(); Console.WriteLine(sh.ShapeName()); sh = new Triangle(); Console.WriteLine(sh.ShapeName()); Console.ReadLine(); } class Shape { public virtual string ShapeName() { return "Фигура"; } } class Hexagon : Shape { public override string ShapeName() { return "Многоугольник"; } } class Square : Hexagon { public override string ShapeName() { return "Квадрат"; } } class Triangle : Hexagon { public new string ShapeName() { return "Треугольник"; } }

А БСТРАКТНЫЙ МЕТОД И АБСТРАКТНЫЙ КЛАСС abstract class A { public abstract void GetName() ; } Абстрактный метод не содержит реализации Абстрактный метод задают функциональность, которая должна быть реализована в классах потомках. Класс имеющих хоть 1 абстрактный метод должен быть объявлен как абстрактный Нельзя создать экземпляр абстрактного класса Потомки обязаны реализовать абстрактные члены или должны быть сами объявлены как абстрактные. Виртуальные методы МОГУТ быть переопределены в потомках, абстрактные – ДОЛЖНЫ быть переопределены в потомках Пример: abstract class A {public abstract void GetName() ; } class B {public override void GetName() { реализация }

И НКАПСУЛЯЦИЯ Сокрытие реализации, деталей Достигается с помощью модификаторов доступа public – член класса виден всем protected – член класса виден только внутри самого класса и внутри потомков private – виден только внутри объявившего его класса (по умолчанию) internal – виден только внутри сборки protected internal – виден только внутри сборки и внутри потомков Модификаторов доступа применяются также и к типам public – класс (тип) виден всем internal – класс(тип) виден только внутри сборки (по умолчанию) В качестве члена класса может выступать и другой тип. Тогда к нему применимы модификаторы доступа к члену класса

Ч ЛЕНЫ КЛАССА

Поля Константы Методы Свойства Конструкторы Деструкторы (Финализаторы) Индексаторы Вложенные типы Переопределение операций Переопределение операций приведения типов Явные Неявные События

Ч ЛЕНЫ КЛАССА Поле – содержит данные класса Константы – определяют магические величины Метод – выполнят действия (над данными) Свойство (С#) – виртуальное поле (совокупность методов get и set) Конструктор – метод, автоматически вызываемы при создании объекта Деструктор (финализатор)– метод, автоматически вызываемы при удалении объекта Индексаторы – позволяют работать с объектом как с массивом Методы переопределения операций

П ОЛЕ Содержит данные Синтаксис [attributes] [modifiers] field_type field_name [=initial_value] [, field_nameN [=initial_valueN] ]; Примеры public readonly double x, y, z; private static int nObjects; private DateTime dateOfBirth; private int i=5, j, k =18; protected object obj=new object();

М ОДИФИКАТОР READONLY Задает поле, доступное только для чтения. Поле readonly можно задать только непосредственно при объявлении или в конструкторе. Изменение такого поля вне конструктора запрещено. Пример: class A { private readonly int j = 8; private readonly int i; public A(int i) {this.i = i;} public TryChange(int k) {i=k;} // Ошибка } Использование Как обычную переменную

К ОНСТАНТЫ Синтаксис [modifiers] const type_name const_name = const_expr; Константы могут быть только простых типов и строковые Поэтому их применение ограничено – используются для обозначения «магических чисел» Члены-константы всегда статические Использование – как обычные переменные (только чтение)

О БЪЯВЛЕНИЕ МЕТОДА Синтаксис: [attributes] [modifiers] return_type method_name (param_list) {method_body} Примеры: public static void WriteLine(string, params object[] p) { … } public int ExecuteNonQuery() { …} public int Add(object obj) { … } private void Init() { … }

В ЫЗОВ МЕТОДА Синтаксис: expression.metod_name(actual_params) Вызов статического метода type_name.method_name(actual_params) Примеры: double d = Math.Log(x); int j = rnd.Next(0, 10); // rnd - переменная Console.WriteLine(Hello, World!);

О БЪЯВЛЕНИЕ КОНСТРУКТОРА Вызывается при создании объекта Синтаксис: [attributes] [modifiers] class_name (param_list) [:ctor_call] { ctor_body } ctor_call ::= base (actual_params) | this (actual_params) Примеры: class Vector3d { public Vector3d(double x, double y, double z) {X = x; Y = y; Z = z;} public Vector3d(double x) : this (x, x, x) {} } class Square { public Square(int side) : base (side, side {} } При генерации исключения объект все равно будет создан

К ЛЮЧЕВОЕ СЛОВО THIS Обозначает ссылку на текущий объект Используется В конструкциях языка class Vector3d { public Vector3d(double x) : this (x, x, x){}…} При передачи текущего объекта как параметр Print(this); При обращение к членам текущего объекта (при сокрытии) class Customer{ string name; void Customer (string name) {this.name = name} …} this не может использоваться в статических членах Доступен как в классах так и в структурах

К ЛЮЧЕВОЕ СЛОВО BASE Обозначает ссылку на текущий родительский класс Используется В конструкциях языка class Vector3d { public Vector3d(double x) : base(x, x, x){}…} При вызове функционала базового класса public override void Print (string text) { … base.Print(text + еще и мой текст); }

М ОДИФИКАТОР STATIC static – член уровня класса, а не экземпляра класса. Единый для всех экземпляров данного класса Обращение к статическому члену Имя_типа.Член_Типа Пример: Console.WriteLine(…) Статический член может использовать только статические члены. class Program { static void Main(string[] args) { Count c = new Count(); c.Inc(); Console.WriteLine(Count.number); Count c2 = new Count(); c2.Inc(); Console.WriteLine(Count.number); Console.ReadLine(); } class Count { public static int number = 0; public void Inc() { ++number; } } Результат 1 2

С ТАТИЧЕСКИЙ КОНСТРУКТОР Назначение – выполнение действий по инициализации типа Выполняется до обращения к любому статическому члену и до создания первого объекта Статические конструкторы различных типов выполняются в произвольном порядке Синтаксис: static class_name() { ctor_body } Не может иметь модификатор доступа

С ВОЙСТВО Свойство – виртуальное поле Обращение – как к полю: int len = s.Length; page.Title = Hello, World!; Реально при обращении вызывается метод – аксессор Поле может иметь аксессор для чтения ( get ) записи ( set )

О БЪЯВЛЕНИЕ СВОЙСТВА Синтаксис: [attributes] [modifiers] prop_type prop_name { [[access_modifier] get accessor_body] [[access_modifier] set accessor_body] } Пример: public int[] Numbers { get { if(ns == null) ns = {1, 2, 3, 4, 5}; return ns; } private set { ns = value; } }

И СПОЛЬЗОВАНИЕ СВОЙСТВ Ограничение доступа к полям Поля только для чтения Проверка допустимости нового значения Вычислимые «поля» Ленивая инициализация Представление одного поля в нескольких форматах

И НДЕКСАТОР Индексатор – свойство, используемое для перегрузки операции [] В основном используется с различными коллекциями Индексатор не может быть статическим Синтаксис [attributes] [modifiers] ind_type this [param_list] { [[access_modifier] get accessor_body] [[access_modifier] set accessor_body] } Пример: public float this[string koord] { get { if(koord ==X) return fx; else if(koord ==Y) return fy;} set { if(koord ==X) fx = value; else if(koord ==Y) fy = value;}

П ЕРЕГРУЗКА ФУНКЦИЙ ( OVERLOADING ) Перегрузка функций – объявление нескольких функций с одинаковым именем и разной сигнатурой Сигнатура функции включает имя функции, а также список формальных параметров Сигнатура не включает возвращаемого значения ! Примеры: int Inc(int i) {…} double Inc (double d) {…} int Inc(int i, long j ) {…} double Inc (int d) {…} // Ошибка

П ЕРЕГРУЗКА ОПЕРАЦИЙ В отличие от некоторых языков, C# позволяет перегружать операции Перегружать можно Арифметические операции Унарные Бинарные Операции приведения Методы, перегружающие операцию – статические

П ЕРЕГРУЗКА АРИФМЕТИЧЕСКИХ ОПЕРАЦИЙ Унарные операции public static operator operation(source_type param_name) Бинарные операции public static operator operation(source_type param_name, source_type2 param_name2) Хотя бы один из двух параметров должен совпадать с типом, содержащим оператор Пример public static Vector operator +(Vector a, Vector b) { return new Vector(a.fx + b.fx, a.fy + b.fy); }

П ЕРЕГРУЗКА ОПЕРАЦИЙ ПРИВЕДЕНИЯ ТИПА Явное приведение public static explicit operator result_type(source_type param_name) Неявное приведение public static implicit operator result_type(source_type param_name) Один из двух типов должен совпадать с типом, содержащим оператор Примеры: public static implicit operator Vector3D(int x) { return new Vector3D(x, 0, 0); } public static explicit operator float(Vector3D v) { return v.fx; }

Д ОПОЛНИТЕЛЬНЫЙ СВЕДЕНИЯ О СТРУКТУРАХ И КЛАССАХ

О ТЛИЧИЕ КЛАССА ОТ СТРУКТУРЫ Большинство синтаксиса и возможностей одинаковые Класс- ссылочный тип, структура – тип-значение При приравнивании структуры значения всех полей копируется, а при приравнивании класса – копируется только ссылка на класс Поля в структуре не могут быть проинициализированы при описании (не относится к константам и статическим полям) Структура не может переопределять конструктор по умолчанию (без параметров) и деструктор В отличии от класса, структура может создаваться без ключевого слова new Структура не может быть явно унаследована и не может является источником наследования. Все структуры неявно унаследованы от типа System.ValueType, который унаследован от object. Структура также как и класс может реализовывать интерфейсы Структура может использоваться как Nullable тип, который может принимать значения null.

К ОНСТРУКТОР ПО УМОЛЧАНИЮ Class Если не указано ни оного конструктора Visual Studio создает конструктор по умолчанию public ИмяТипа ( ){ } Если задается любой конструктор, конструктор по умолчанию не добавляется Struct Всегда имеет неявный public конструктор по умолчанию и его нельзя переопределить Можно заводить дополнительные конструкторы ComplexStruct myStruct = new ComplexStruct(5,7); Дополнительные конструкторы должны проинициализировать все поля или вызвать конструктор по умолчанию

М ОДИФИКАТОР КЛАССА SEALED От класса, помеченного как sealed, нельзя наследоваться Использование В классах отвечающих за безопасность Нельзя в потомках получить доступ к незащищенным инкапсулированным данным Нельзя подменить алгоритмы обеспечения безопасности Для повышения быстродействия Отключается поиск переопределения виртуальных методов public sealed class MySecurity { …}

М ОДИФИКАТОР PARTIAL Для класса, структуры и интерфейса partial тип может быть определен в разных файлах одного модуля Все части partial типа должны быть определены внутри одного модуля Все partial части должны иметь одинаковое имя Компилятор склеит все partial части типа в один тип при компиляции Строка наследования и реализуемых интерфейсов тоже будет склеена (одинаковые типы удалятся) partial class A : B, IC {} partial class A : B, ID {} partial class A : ID {} partial class A {} partial class A : B, IC {} partial class A : B, ID {} partial class A : ID {} partial class A {} class A : B, IC, ID { суммарный код} class A : B, IC, ID { суммарный код} Используется для разбиения на части большого сложного типа и реализации разных логических частей в разных файлах

М ОДИФИКАТОР PARTIAL Для метода Только внутри partial класса или структуры Метод должен возвращать void Не допускается использовать модификатор доступа. Он всегда неявно private Сигнатуры методов должны совпадать В одной части должно быть объявление метода В другой может быть реализация Если реализации нет, то все вызовы метода удаляются при компиляции partial void partial void OnSomethingHappened(string s); partial void partial void OnSomethingHappened(String s) { Console.WriteLine("Something happened: {0}", s); } partial void partial void OnSomethingHappened(String s) { Console.WriteLine("Something happened: {0}", s); }

Р АСШИРЕННЫЙ СИНТАКСИС ИНИЦИАЛИЗАЦИИ После конструктора в { } можно задавать публичные свойства При этом можно опускать () при вызове конструктора по умолчанию class Complex { public double Re { get; set; } public double Im { get; set; } public Complex() { } public Complex(double re) { Re = re; } } … Complex c1 = new Complex() { Re = 5, Im = 7 }; Complex c2 = new Complex() { Im = 7 }; Complex c3 = new Complex { Im = 7 }; Complex c4 = new Complex(5) { Im = 7 };