□ Класс может быть выведен только из одного базового класса (хотя из любого числа интерфейсов). Если базовый класс явно не определен, то класс будет автоматически выводиться из System.Object
, который предоставит ему всю функциональность System.Object
, из которой чаще всего используется ToString()
.
□ Каждый член явно объявляется с модификатором доступа. Не существует эквивалента синтаксису C++, где один модификатор доступа может применяться к нескольким членам.
public: // нельзя использовать этот синтаксис в C#
int MyMethod();
int MyOtherMethod();
□ Методы не могут объявляться как inline
. Это связано с тем, что C# компилируется в промежуточный язык (IL). Любые вставки кода происходят на второй стадии компиляции, когда JIT-компилятор выполняет преобразование из IL в собственный код машины. JIT-компилятор имеет доступ ко всей информации в IL при определении, какие методы могут подходить для вставки без необходимости каких-либо указаний в исходном коде разработчика.
□ Реализация методов всегда помещается вместе с определением. Невозможно написать реализацию вне класса, как позволяет C++.
□ В то время как в ANSI C++ единственными типами члена класса являются переменные, функции, конструкторы, деструкторы и перезагружаемые версии операторов, C# имеет в наличии также делегатов, события и свойства.
□ Модификаторы доступа public
, private
и protected
обладают тем же самым значением, как и в C++, но существуют два дополнительных модификатора доступа:
□ internal
ограничивает доступ к другому коду внутри той же сборки.
□ protected internal
ограничивает доступ к производным классам, которые находятся внутри той же сборки.
□ Инициализация переменных разрешается в C# в определении класса.
□ В C++ ставится точка с запятой после закрывающейся фигурной скобки в конце определения класса. Это не требуется в C#.
Инициализация полей членов
Синтаксис, используемый для инициализации полей членов в C#, очень отличается от синтаксиса C ++, хотя конечный результат одинаковый.
В C++ поля членов экземпляра обычно инициализируются в списке инициализации конструктора:
MyClass::MyClass() : m_MyField(6) {
// и т.д.
В C# этот синтаксис недопустим. Можно помещать в инициализатор конструктора (который является эквивалентом C# списка инициализации конструктора в C++) другой конструктор. Вместо этого инициализированное значение помечается с помощью определения члена в определении класса:
class MyClass {
private int MyField = 6;
Отметим, что в C++ это будет ошибкой, так как C++ использует примерно такой же синтаксис для определения чисто виртуальных функций. В C# такое действие считается нормой, так как C# не применяет синтаксис =0
для этой цели (он использует вместо этого ключевое слово abstract
).
В C++ статические поля инициализируются с помощью отдельного определения вне класса:
int MyClass:MyStaticField = 6;
На самом деле в C++, даже если не требуется инициализировать статическое поле, необходимо включить эту инструкцию, чтобы избежать ошибки компоновки. В противоположность этому C# не ожидает подобной инструкции, так как в C# переменные объявляются только в одном месте:
Class MyClass {
private static int MyStaticField = 6;
Конструкторы
Синтаксис объявления конструкторов в C# такой же, как синтаксис для встраиваемых конструкторов, заданных в определении класса в C++.
class MyClass {
publiс MyClass() {
// код конструктора
}
Как и в C++, можно определить столько конструкторов, сколько потребуется, при условии, что они получают различное число или типы параметров. (Отметим, что, как и в методах, параметры по умолчанию не допускаются, необходимо моделировать это с помощью нескольких перезагружаемых версий.)
Для производных классов иерархии конструкторы действуют в C# по сути таким же образом, как и в C++. По умолчанию конструктор на вершине иерархии (это всегда System.Object
) выполняется первым, за ним следуют конструкторы в порядке, определяемом деревом иерархии.
Статические конструкторы
C# допускает также концепцию статического конструктора, который выполняется только один раз и может использоваться для инициализации статических переменных. Концепция не имеет прямого эквивалента в C++.
class MyClass {
static MyClass() {
// код статического конструкторе
}
Статические конструкторы очень полезны тем, что позволяют инициализировать статические поля с помощью значений, которые определяются во время выполнения (например, они могут задаваться значениями которые считываются из базы данных). Такой результат возможен в C++, но требует определенной работы, и решение обычно выглядит беспорядочным. Наиболее общий подход должен иметь функцию, которая обращается к статическим переменным членам, и функция будет реализована таким образом, что она задает значение переменной при первом вызове.
Отметим, что статический конструктор не имеет спецификатора доступа, он не объявляется как открытый, закрытый или как-нибудь еще. Спецификатор доступа не будет иметь смысла, так как статический конструктор вызывается только средой выполнения .NET, когда загружается определение класса. Он не может вызываться никаким другим кодом C#.
C# не задает точно, когда будет выполнен статический конструктор, за исключением только того, что это произойдет после инициализации всех статических полей, но перед тем, как будет создан какой-либо объект класса, или там, где статические методы класса реально используются.