Ответ
Краткий ответ: Зависит от способа сравнения. При использовании переопределенного метода Equals() или оператора == для структуры боксинга не происходит. Боксинг может случиться при приведении структуры к типу интерфейса или при вызове унаследованного от object метода.
Детали и примеры:
-
Сравнение БЕЗ боксинга (рекомендуемый способ):
public readonly struct Point : IEquatable<Point> { public int X { get; } public int Y { get; } // Реализация IEquatable<T> избегает боксинга public bool Equals(Point other) => X == other.X && Y == other.Y; // Переопределение Equals(object) требует боксинга для 'obj', но это редко используемый путь public override bool Equals(object obj) => obj is Point other && Equals(other); // Перегрузка оператора == public static bool operator ==(Point left, Point right) => left.Equals(right); } Point p1 = new Point(1, 2); Point p2 = new Point(1, 2); bool isEqual1 = p1.Equals(p2); // НЕТ боксинга (вызов IEquatable<Point>.Equals) bool isEqual2 = p1 == p2; // НЕТ боксинга (вызов перегруженного оператора) -
Сравнение, которое ВЫЗЫВАЕТ боксинг:
Point p1 = new Point(1, 2); Point p2 = new Point(1, 2); // БОКСИНГ: Приведение к необобщенному интерфейсу IEquatable ie = p1; // Боксинг для p1! bool isEqual3 = p1.Equals((object)p2); // Боксинг для p2 (вызов Equals(object)) // БОКСИНГ: Использование в коллекциях типа object (например, ArrayList) ArrayList list = new ArrayList(); list.Add(p1); // Боксинг при добавлении!
Почему это важно? Боксинг создает новый объект в куче (heap), что приводит к дополнительным затратам на выделение памяти и последующую сборку мусора (GC). В высокопроизводительном коде или в циклах это может стать узким местом. Всегда реализуйте для структур интерфейс IEquatable<T> и используйте обобщенные коллекции (List<Point> вместо ArrayList).