Какой самый базовый предок (корневой тип) всех объектов в .NET?

«Какой самый базовый предок (корневой тип) всех объектов в .NET?» — вопрос из категории C# Core, который задают на 25% собеседований C# Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Корневым предком для всех типов в .NET (как ссылочных class, так и значимых struct) является тип System.Object (синоним в C# — ключевое слово object).

Почему это важно? Это обеспечивает единую систему типов. Любой экземпляр можно присвоить переменной типа object (для значимых типов это потребует упаковки — boxing).

Базовые виртуальные методы, предоставляемые Object:

Метод Назначение Особенности переопределения
Equals(object) Определяет равенство объектов по значению. При переопределении обязательно переопределите GetHashCode().
GetHashCode() Возвращает хэш-код для использования в хэш-таблицах (Dictionary, HashSet). Должен возвращать одинаковое значение для равных объектов.
ToString() Возвращает строковое представление объекта. По умолчанию выводит полное имя типа. Всегда полезно переопределять для отладки.
GetType() Возвращает экземпляр Type, описывающий тип объекта во время выполнения (RTTI). Не виртуальный, его нельзя переопределить.
MemberwiseClone() Создает поверхностную (shallow) копию объекта. Защищенный метод.
ReferenceEquals() Статический метод для сравнения ссылок.

Пример на C#:

// Все эти присваивания корректны благодаря System.Object
object obj1 = new MyClass(); // Ссылочный тип
object obj2 = 42; // Значимый тип (int) -> происходит boxing
object obj3 = "Hello"; // Строка (ссылочный тип)

Console.WriteLine(obj2.GetType()); // Вывод: System.Int32
Console.WriteLine(obj1.Equals(obj3)); // Вывод: False (сравнение по умолчанию — по ссылке)

// Пример переопределения ToString() в своем классе
public class Product
{
    public int Id { get; set; }
    public string Name { get; set; }

    public override string ToString() => $"Product {{ Id = {Id}, Name = {Name} }}";
}

var product = new Product { Id = 1, Name = "Laptop" };
Console.WriteLine(product); // Вывод: Product { Id = 1, Name = Laptop }