Организация памяти
Простые типы и структуры (если не созданы оператором new) хранятся по значению (внутри классов, будучи локальными переменными - в стеке), другие типы – массивы, классы, интерфейсы, делегаты, события хранятся по ссылке. Данные, созданные оператором new и данные ссылочных типов удаляются автоматически, их адреса могут меняться, чтобы уплотнить память. Чтобы обращаться через указатель к такому данному используется оператор fixed.
unsafe void f(int[] a) {fixed(int* b=a) {T* c(T*)(void*)&b[5]; c->d=5;}} Оператор fixed блокирует изменение адреса объекта a.
object – предопределенный класс, обеспечивающий хранения по ссылке, он является базовым для всех ссылочных типов.
”->” везде заменяется на ”.”. (”->” может использоваться внутри fixed (…) {..} см. далее. ”::” в языке отсутствует.)
Оператор delete отсутствует.
Типы
Простые типы, строки
sbyte – байт со знаком, byte – байт без знака, ushort, uint, ulong, decimal – числовые типы, char – расширенный символ.
10f, 1.1d, 1.1m – f,d,m - модификаторы значений, определяющие типы float, double, decimal.
string – предопределенный класс, данное которого является строкой Unicode.
string s = @"\\ \t \n"; Знак @ обозначает дословность всех символов внутри кавычек.
s=3.ToString(); Любые типы, в том числе, простые, неявно преобразуются в objectboxing conversion). (
object o=3;
int n=o; - unboxing conversion.
Массивы
int[][] a={{1,2},{3,4,5}}; Массив массивов. Элементы могут иметь разную длину.
int [,] a=new int[,] {{1,2,3},{2,3,4}}; Двумерный массив.
a=new int[,] {{1,2},{1,2},{1,2}};
a=new int[20,10];
a.Length – количество элементов.
События
delegate void F(int);
event F e; Событие – список делегатов. Оно может быть оформлено как свойство, то есть иметь конструкцию {get{…}, set{…}}.
e+= new F(x.g); e-= new F(x.g); e=null; Допустимые операции со свойствами. g – метод объекта x.
Атрибуты
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface, AllowMultiple=true)]
public class MyAttribute: System.Attribute
{ public MyAttribute (string authorName) {…}
public string Date {get {…} set {…}}
public int Label {get {…} set {…}}
}
[AttributeUsage(AttributeTargets.Parameter)]
public class XAttribute: System.Attribute
{ public XAttribute () {…}}
[Author("Иванов", Date="16.02.2000", Label=5), Author("Петров", Label=3)]
class T
{ [Author("Иванов")] void f([X] int a, int b) {…}
[Author("Петров")] void g(float x, [X] float y) {…}
}
[Author("Петров")]
class T1 {void h() {int n=topeof(T).GetCustommAttributes(typeof(MyAttribute)).Label;}}}
Атрибуты являются классами, производными от класса System.Attribute. Каждый конструктор атрибута определяет возможный набор позиционных параметров. Свойства атрибута (Date, Label) определяют возможные именованные параметры. Позиционные и именованные параметры могут быть типов: bool, byte, char, double, float, int, long, short, string, object, System.Type. Чтобы создать атрибут, которым можно сопровождать различные элементы программы нужно его определение сопроводить атрибутом AttributeUsage, в котором задается какие элементы можно будет сопровождать новым атрибутом: Assembly, Module, Class, Struct, Enum, Constructor, Method, Property, Field, Event, Interface, Parameter, Delegate, можно ли обладать атрибутом несколько раз и наследуется ли этот атрибут (?). Чтобы сопроводить какой-то элемент программы атрибутом нужно, перед его определением в квадратных скобках поместить его инициализацию, состоящую из его имени (если оно кончается на Attribute, то Attribute можно сократить), за которым в скобках могут следовать параметры. Параметры могут задаваться выражениями или одномерным массивом (?).
Создан набор атрибутов, позволяющих помечать классы, их методы и т.д., чтобы из них создавались или в них импортировались COM объекты. Этот механизм использован в .NET технологии.
Предопределенные атрибуты Conditional и Obsolete
class T {[Conditional(”A”)] void f() {…} } эквивалентно:
class T {
#ifdef A
void f() {…}
#endif
}
class T {[Obsolete] void f() {…}} Указывает на то, что f не должна больше использоваться.
Импорт методов[/COLOR]
class T { [DllImport("mydll", setLastError=true)] static extern void F1(); …} функция F1 импортируется из ”mydll.dll”. Нельзя из dll импортировать нестатические методы.
Поддержка версий
Каждый разработчик пишет свои пространства имен, внутри которых используются чужие. Разработчики независимо друг от друга изменяют невидимые члены классов и внутренности методов классов этих пространств. Утверждается, что все будет работать без перекомпиляции.