Содержание
object (System.Object) — окончательный базовый класс для всех типов. Любой тип может быть автоматически (скрыто) приведен к базовому классу (upcast) object.
Эта особенность может быть очень полезна при создании универсальных хранилищ, например:
| 1 2 3 4 5 6 7 | public class Stack {     int position;     object[] data = new object[10];     public void Push (object o) { data[position++] = o; }     public object Pop() { return data[--position]; } } | 
 Поскольку Stack работает с типом object, в него можно добавлять (Push) и удалять (Pop) экземпляры любого типа.
object — ссылочный тип, но не смотря на это значимые типы также могут быть приведены к типу object (и обратно из него). Чтобы сделать это возможным, CLR должна проделать ряд приготовлений, чтобы устранить различия между ссылочными и значимыми типами. Этот процесс называется приведение к объектному типу (boxing) и восстановление значения из объектного образа (unboxing).
Приведение к объектному типу (boxing) и восстановление значения из объектного образа (unboxing)
Приведение к объектному типу (boxing) — процесс приведения экземпляра значимого типа к ссылочному типу. Ссылочным типом в данном случае может быть либо класс object, либо интерфейс. Восстановление значения из объектного образа (unboxing) — обратный процесс, приведение object назад к изначальному значимому типу.
| 1 2 3 | int x = 9; object obj = x; // Boxing int y = (int)obj; // Unboxing | 
 Восстановление значения требует явного приведения, при этом проверяется, что указанный значимый тип соответствует реальному типу объекта, и если это не так выбрасывается InvalidCastException.
| 1 2 3 4 5 6 | object obj = 9; // 9 - тип int long x = (long) obj; // InvalidCastException, т.к. int и long полностью не соотносятся long x = (int) obj; // А так допустимо object obj = 3.5; // 3.5 - тип double int x = (int) (double) obj; // x = 3, (double) выполняет восстановление значения,                              // (int) - приведение к типу int | 
При приведении к объектному типу экземпляр значимого тип копируется в новый объект, а при восстановлении значения содержимое объекта копируется назад в экземпляр значимого типа.
| 1 2 3 4 | int i = 3; object boxed = i; i = 5; Console.WriteLine (boxed); // 3 | 
Проверка типа
C# проверяет тип два раза: статически (во время компиляции) и во время выполнения программы. Статическая проверка типа позволяет компилятору проверить программу без ее запуска. Следующий пример не будет скомпилирован благодаря статической проверке типа:
| 1 | int x = "5"; | 
Проверка типа во время выполнения выполняется средой CLR при приведении к типу производного класса (downcast) и при восстановлении значения (unboxing).
| 1 2 | object y = "5"; int z = (int) y; // Ошибка во время выполнения при downcast | 
Метод GetType и оператор typeof
Проверка типа во время выполнения возможна благодаря тому, что каждый объект хранит маленький маркер типа. Этот маркер в свою очередь сам является объектом типа System.Type. Есть два способа получить объект System.Type:
- вызвать метод GetTypeу проверяемого экземпляра объекта (вычисляется во время выполнения)
- использовать оператор typeofс именем типа (вычисляется статически при компиляции)
System.Type имеет свойства для таких вещей как имя типа, сборка, базовый тип и т.д., а также ряд методов.
| 1 2 3 4 5 | int x = 3; Console.Write (x.GetType().Name); // Int32 Console.Write (typeof(int).Name); // Int32 Console.Write (x.GetType().FullName); // System.Int32 Console.Write (x.GetType() == typeof(int)); // True | 
Список членов типа object
- public extern Type GetType();
- public virtual bool Equals (object obj);
- public static bool Equals (object objA, object objB);
- public static bool ReferenceEquals (object objA, object objB);
- public virtual int GetHashCode();
- public virtual string ToString();
- protected override void Finalize();
- protected extern object MemberwiseClone();
Equals, ReferenceEquals и GetHashCode
Метод класса object Equals схож с оператором ==, за исключением того, что Equals виртуальный (virtual), а == статический (static).
| 1 2 3 4 | object x = 3; object y = 3; Console.WriteLine (x == y); // False Console.WriteLine (x.Equals (y)); // True | 
 Поскольку x и y приводятся к типу object, компилятор использует объектный оператор ==, который сравнивает объекты по ссылке (и поскольку x и y приведены к объектному типу, они являются двумя разными объектами, отдельно хранящимися в памяти, и поэтому не равны).
Однако виртуальный метод Equals отсылает к методу Equals типа Int32, который сравнивает объекты по значению.
Статический метод object.Equals просто вызывает виртуальный метод Equals для первого аргумента, предварительно проверив что оба аргумента не равны null.
| 1 2 3 | object x = null, y = 3; bool error = x.Equals (y); // Ошибка при выполнении bool ok = object.Equals (x, y); // Без ошибки вернет false | 
 Метод ReferenceEquals принудительно сравнивает объекты по ссылке (это может быть удобно для ссылочных типов если оператор == перегружен и выполняет иное действие).
Метод GetHashCode извлекает хэш-код, который может быть использован в словарях, основанных на хэш-таблицах (System.Collections.Generic.Dictionary и System.Collections.Hashtable).
Метод ToString
Метод ToString возвращает текстовое представление по умолчанию экземпляра типа. Этот метод переопределен для всех предопределенных типов.
| 1 2 | string s1 = 1.ToString(); // s1 = "1" string s2 = true.ToString(); // s2 = "True" | 
| 1 | public override string ToString() { return "Foo"; } | 

