Я намагаюся зібрати всі ситуації, в яких бокс відбувається в C #:
Перетворення типу значення в
System.Object
тип:struct S { } object box = new S();
Перетворення типу значення в
System.ValueType
тип:struct S { } System.ValueType box = new S();
Перетворення значення типу перерахування в
System.Enum
тип:enum E { A } System.Enum box = E.A;
Перетворення типу значення у посилання на інтерфейс:
interface I { } struct S : I { } I box = new S();
Використання типів значень у конкатенації рядків C #:
char c = F(); string s1 = "char value will box" + c;
Примітка: константи
char
типу об'єднуються під час компіляціїпримітка: починаючи з версії 6.0 C # компілятор оптимізує конкатенація з участю
bool
,char
,IntPtr
,UIntPtr
типиСтворення делегата з методу екземпляра типу значення:
struct S { public void M() {} } Action box = new S().M;
Виклик неперезаписаних віртуальних методів для типів значень:
enum E { A } E.A.GetHashCode();
Використання шаблонів констант C # 7.0 під
is
виразом:int x = …; if (x is 42) { … } // boxes both 'x' and '42'!
Бокс у перетвореннях типів кортежів на C #:
(int, byte) _tuple; public (object, object) M() { return _tuple; // 2x boxing }
Необов’язкові параметри
object
типу зі значеннями типу значення за замовчуванням:void M([Optional, DefaultParameterValue(42)] object o); M(); // boxing at call-site
Контрольне значення необмеженого загального типу для
null
:bool M<T>(T t) => t != null; string M<T>(T t) => t?.ToString(); // ?. checks for null M(42);
Примітка: це може бути оптимізовано JIT в деяких середовищах виконання .NET
Значення тестування типу необмеженого або
struct
загального типу за допомогою операторівis
/as
:bool M<T>(T t) => t is int; int? M<T>(T t) => t as int?; IEquatable<T> M<T>(T t) => t as IEquatable<T>; M(42);
Примітка: це може бути оптимізовано JIT в деяких середовищах виконання .NET
Чи є ще такі ситуації боксу, можливо, приховані, про які ви знаєте?