Рассмотрим следующий сценарий:
int Caller1<T>(T t) where T : IInterface {...}
T Caller2<T>() where T : IInterface {...}
class Wrappee // doesn't implement IInterface, but could
??? Wrapper : IInterface {
private readonly Wrappee _wrappee;
// methods call _wrappee's methods
}
Теперь общий совет для выбора между struct
и class
: «используйте struct
, если вам нужна семантика значения, и class
для ссылочной семантики». Нам нужна семантика "ссылка на Wrappee
". Но кажется, что мы все еще можем сделать Wrapper
структурой: копирование его значения такое же, как копирование ссылки Wrappee
, и копии будут иметь ссылку на тот же объект ! Накладные расходы ниже, и скалярная замена может уменьшить его до нуля для локальных переменных. Кажется, можно вызывать даже мутантные методы на _wrappee
.
Я что-то упустил? Есть ли веская причина, чтобы вместо этого сделать Wrapper
классом?
Существует один, если вызывающий абонент не является общим:
int Caller(IInterface t) {...}
В этом случае Wrapper
должен быть классом, чтобы избежать бокса.
Замечание для тех, кто знает Haskell: я пытаюсь найти ближайший аналог .NET для newtype
.
ОБНОВЛЕНИЕ: См. Профессиональные .NET 2.0 Generics и Питер Ричи на форумах MSDN об отсутствии бокса в первом случае.