- •Обзор элементов класса.
- •Класс Object
- •Структуры
- •Методы Ссылочные параметры ref и out
- •Переменное число аргументов метода
- •Перегрузка методов. Вызов методов с одинаковым именем и разными аргументами
- •Конструкторы экземпляра
- •Вызов конструктора экземпляра
- •Закрытые конструкторы экземпляра
- •Статические конструкторы
- •Конструкторы структур
- •Член со спецификатором readonly
- •Деструкторы. Сборка мусора
- •Объект Account
- •Объект Account недоступен
- •Свойства
- •Индексаторы
- •Предпосылки появления наследования
- •Синтаксис наследования.
- •Типы наследования
- •Множественное наследование
- •Наследование интерфейса
- •Виртуальные методы
- •Спецификаторы доступности
- •Вызов базовых версий функций
- •Абстрактные классы и функции
- •Структуры и наследование
- •Полиморфизм
- •Потеря и восстановление информации о типе
- •Операции is и as
- •Файловый ввод-вывод
- •Потоки данных и файловый ввод-вывод
- •Виды файлов
- •Классы файлового ввода-вывода
- •Класс FileInfo
- •Текстовый ввод-вывод при помощи Stream Reader и Stream Writer
- •Бинарный ввод и вывод при помощи класса FileStream
Класс Object
Классы .NET изначально унаследованы от System.Object. Фактически, если не указывать базовый класс при определении нового класса, компилятор автоматически предполагает, что он наследуется от Object. Все классы, которые мы видели до сих пор, на самом деле унаследованы от System.Object. (Как упоминалось выше, для структур это наследование непрямое. Структуры всегда наследуются от System. ValueType, который, в свою очередь, унаследован от System.Object.)
Практическое значение этого в том, что помимо методов и свойств, которые вы определяете, вы также получаете доступ к множеству общедоступных и защищенных методов-членов, которые определены в классе Object. Эти методы присутствуют во всех классах, которые вы определяете.
Структуры
В большинстве случаев чаще используются классы, нежели структуры. Классы великолепно обеспечивают инкапсуляцию объектов в программах, они сохраняются в куче, обеспечивая таким образом гибкость в отношении времени жизни данных. Однако в некоторых ситуациях все, что необходимо – маленькая структура данных. В этом случае класс предоставляет больше функциональности, чем требуется, и из соображений производительности можно отдать предпочтение структуре.
Рассмотрим пример:
class Dimensions
public double Length;
public double Width;
Этот код определяет класс Dimensions, который просто сохраняет длину и ширину некоторого элемента. Все, что нужно — два числа, которые удобнее хранить вместе, чем по отдельности. Как упоминалось ранее единственное, что нужно изменить в чтобы сделать этот тип структурой вместо класса — это просто заменить ключевое class на struct:
struct Dimensions
public double Length;
public double Width;
Определение функций для структур выглядит точно так же, как определение для классов. Следующий код демонстрирует структуру с конструктором и свойством:
struct Dim
{
public int a;
public int b;
Dim(int new_a, int new_b)
{
a = new_a;
b = new_b;
}
public int area
{
get
{
return a*b;
}
}
}
Во многих отношениях структуры С# можно воспринимать как упрощенные классы, В основном они такие же, как классы, но предназначены в большей степени для тех случаев когда необходимо просто группировать некоторые данные в одном месте.
Отличия структур от классов заключаются в следующем:
Структуры — это типы значений, а не ссылочные типы. Это значит, что он либо сохраняются в стеке, либо являются встроенными (последнее — если они являются частью другого объекта, хранимого в куче), и имеют те же ограничения времени жизни, что и простые типы данных.
Структуры не поддерживают наследование.
Существует некоторое отличие в работе конструкторов структур. В частности компилятор всегда генерирует конструктор по умолчанию без параметров, который переопределить невозможно.
Поскольку структуры на самом деле предназначены для группирования данных, в большинстве случаев все их поля объявляются общедоступными. Строго говоря, это противоречит рекомендациям по написанию кода .NET. Согласно Microsoft, поля (кроме константных) всегда должны быть приватными и помещенными в оболочки общедоступных свойств. Однако что касается простых структур, многие разработчики считают применение общедоступных полей допустимой практикой программирования.
Стоит отметить, что реализация структур C++ и С# серьезно отличается, от реализации классов. В этом смысле ситуация совсем не похожа на C++, где структуры и классы - практически одно и тоже.
Допишем программу:
class Program
{
static void Main(string[] args)
{
Dim dim_1;
dim_1.b = 5;
dim_1.a = 6;
Console.WriteLine(dim_1.area);
Console.ReadLine();
}
}
Хотя структуры относятся к типам значений, очень часто их можно трактовать так же, как классы. Например, имея определение класса Dim из предыдущего примера, можно написать:
Dim dim_1 = new Dim();
dim_1.b = 5;
dim_1.a = 6;
Обратите внимание, что поскольку структуры являются типами значений, операция new с ними работает несколько иначе, чем с классами и другими ссылочными типами. Вместо того чтобы выделять память в куче, операция new просто вызывает подходящий конструктор, инициализируя поля в соответствии с переданными ему параметрами. В самом деле, для структур можно написать:
Dim dim_1;
dim_1.b = 5;
dim_1.a = 6;
Если бы dim_1 был классом, это привело бы к ошибке компиляции, потом) что point содержал бы неинициализированную ссылку — то есть адрес, никуда не указывающий, а потому было бы невозможно присваивать значения его полям. Для структур же объявление переменной на самом деле выделяет пространство в стеке для полной структуры, поэтому она тут же готова к присвоению значений полям.
Структуры следуют тем же правилам, что и все другие типы данных: все должно быть инициализировано перед использованием. Структура рассматривается как полностью инициализированная, когда для ее создания была вызвана операция new, или же когда всем ее полям индивидуально были присвоены значения. И естественно структура, определенная как поле класса, инициализируется автоматическим обнулением при инициализации ее включающего объекта.
Тот факт, что структуры — это типы значений, оказывает влияние на производительность. В зависимости от того, как использовать структуры, это может быть и плохо и хорошо. Положительным является то, что выделение памяти для структур происходит очень быстро, потому что они встроены или размещаются в стеке. То же самое касается удаления структур при выходе из контекста. С другой стороны, всякий раз когда вы передаете структуру в виде параметра, или присваиваете одну структуру другой (как в А=В, когда А и В — структуры), то происходит копирование всего содержимого структуры, в то время как в случае с классами копируется только ссылка. Это приводит к потерям производительности, которые зависят от размера структуры — это подчеркивает тот факт, что структуры на самом деле предназначены для хранения небольших порций данных. Отметим, однако, что когда структура передается методу в виде параметра, этих потерь производительности можно избежать, применяя ref - параметры — при этом передается только адрес в памяти, где находится структура. Это так же быстро, как и передача объекта класса. С другой стороны, если так делать, то необходимо помнить, что вызываемый метод может в принципе изменить значение переданной структуры.