Тип оболочки в .NET: структура или класс? - PullRequest
2 голосов
/ 31 июля 2009

Рассмотрим следующий сценарий:

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 об отсутствии бокса в первом случае.

Ответы [ 3 ]

4 голосов
/ 31 июля 2009

Да, так как вы будете обращаться к оболочке через переменную IInterface, чтобы избежать упаковок, это должен быть класс.

РЕДАКТИРОВАТЬ: Если вы обращаетесь к оболочке через переменную, типизированную как Wrapper, и обращаетесь к методам Wrapper, а не к методам IInterface, тогда структура в порядке.

2 голосов
/ 02 августа 2009

Часто ваш класс / структура будет храниться или передаваться внутренне методами, которые вы вызываете (вы не показали, что делают Caller1 и Caller2), и в этом случае он, вероятно, будет упакован. Возможно, чаще, чем вы ожидали. Поэтому, если вы не докажете, что структура будет более эффективной: не беспокойтесь и просто придерживайтесь класса.

Кроме того, структуры часто не одобряются, если они не представляют что-то вроде типа данных, поэтому выбор класса может помешать будущим обсуждениям другого характера.

Однако, если производительность действительно , и если вы можете гарантировать, что экземпляры передаются только в качестве параметра с ограничением общего типа и никогда не сохраняются в полях или коллекциях с типом интерфейса, текущим встраивание структур в среду выполнения .NET будет более эффективным, так как ваша оболочка-структура будет в основном оптимизирована. Но это много если.

0 голосов
/ 31 июля 2009

Я бы сказал, класс, потому что вы инкапсулируете поведение, а не только данные.

...