Варианты использования для упаковки значения вводят в C#?

Свойство Now выглядит примерно так:

 DateTime Now {
     get {
         // Get the OS time
         return new DateTime(year, month, day, hour, min, sec...)
     }
 }

(технически неверно, Now теперь внутренне вызывает UtcNow, который вызывает ОС :-), но вы поняли идею).

DateTime.Now является фабрикой для DateTime: -)

10
задан felideon 22 June 2009 в 17:39
поделиться

9 ответов

В общем, вам обычно следует избегать упаковки ваших типов значений.

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

Еще есть случаи, когда это может быть полезно в .NET 2.0+. Каждый раз, когда вы хотите воспользоваться преимуществом того факта, что все типы, включая типы значений, можно рассматривать как объект напрямую, вам может потребоваться использовать упаковку / распаковку. Иногда это может быть удобно, поскольку позволяет сохранять любой тип в коллекции (используя объект вместо T в общей коллекции), но в целом этого лучше избегать, поскольку вы теряете безопасность типов.

14
ответ дан 3 December 2019 в 13:29
поделиться

Практически никогда не бывает веских причин для преднамеренной упаковки типа значения. Почти всегда причина для упаковки типа значения состоит в том, чтобы сохранить его в некоторой коллекции, которая не поддерживает типы. Старый ArrayList , например, представляет собой набор объектов, которые являются ссылочными типами. Единственный способ собрать, скажем, целые числа - это упаковать их как объекты и передать их в ArrayList.

В настоящее время у нас есть общие коллекции, так что это не проблема.

13
ответ дан 3 December 2019 в 13:29
поделиться

Упаковка обычно происходит автоматически в .NET, когда это необходимо; часто, когда вы передаете тип значения чему-то, ожидающему ссылочного типа. Типичный пример - string.Format (). Когда вы передаете этому методу примитивные типы значений, они упаковываются как часть вызова. Итак:

int x = 10;
string s = string.Format( "The value of x is {0}", x ); // x is boxed here

Это иллюстрирует простой сценарий, в котором тип значения (x) автоматически упаковывается в коробку для передачи методу, ожидающему объект. Как правило, вы хотите избежать упаковки типов значений, когда это возможно ... но в некоторых случаях это очень полезно.

Что интересно, когда вы используете универсальные шаблоны в .NET, типы значений не упаковываются, когда используются как параметры или члены тип. Это делает универсальные шаблоны более эффективными, чем старый код C # (например, ArrayList), который обрабатывает все как {объект}, не зависящий от типа. Это добавляет еще одну причину использования общих коллекций,

9
ответ дан 3 December 2019 в 13:29
поделиться

Я бы порекомендовал вам 2 хорошие статьи Эрика Липперта

http://blogs.msdn.com/ericlippert/archive/2009/04/27/the-stack-is-an -implementation-detail.aspx

http://blogs.msdn.com/ericlippert/archive/2009/05/04/the-stack-is-an-implementation-detail-part-two.aspx

Здесь это цитата, с которой я согласен на 100%

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

В 99% приложений разработчики не должны заботиться о том, почему типы значений находятся в стеке, а не в куче, и какой прирост производительности мы можем здесь получить. Juts имеет в виду очень простые правила:

  1. Избегайте бокса / распаковки, если это не так. необходимо использовать коллекции дженериков. Большинство проблем возникает не тогда, когда вы определите свои собственные типы, но когда вы правильно использовать существующие типы (определяется Microsoft или вашим коллеги)
  2. Сделайте ваши типы значений просто. Если вам нужна структура с 10-20 полями, полагаю, вы бы лучше создать класс. Представляете, все эти поля будут копироваться каждый раз когда вы иногда передаете это функция по значению ...
  3. Я не думаю, что очень полезно иметь типы значений со ссылочным типом поля внутри. Как структура с Строковые и объектные поля.
  4. Определите, какой тип вам нужен в зависимости от необходимая функциональность, а не где его следует хранить. Структуры имеют ограниченная функциональность по сравнению с классы, поэтому, если структура не может предоставить необходимый функционал, например конструктор по умолчанию, определите класс.
  5. Если что-то может выполнять какие-либо действия с данными других типов, обычно определяется как класс. Для операций со структурами с должны быть определены разные типы только если вы можете привести один тип к другой. Скажем, вы можете добавить int к double, потому что вы можете привести int к double.
  6. Если что-то должно быть без состояния, это класс.
  7. Когда вы сомневаетесь, используйте ссылочные типы. : -)

Любые правила разрешают исключения в особых случаях, но не пытайтесь чрезмерно оптимизировать.

ps Я встретил некоторых разработчиков ASP.NET с 2-3-летним опытом, которые не знают разницы между стеком и кучей. :-( Я бы не стал нанимать такого человека, если бы я был интервьюером, но не потому, что упаковка / распаковка может быть узким местом на любом из сайтов ASP.NET, которые я когда-либо видел.

5
ответ дан 3 December 2019 в 13:29
поделиться

Я думаю, что хороший пример бокса в C # встречается в неуниверсальных коллекциях, таких как ArrayList .

2
ответ дан 3 December 2019 в 13:29
поделиться

Одним из примеров может быть случай, когда метод принимает параметр объекта, а тип значения должен быть передан.

1
ответ дан 3 December 2019 в 13:29
поделиться

Ниже приведены некоторые примеры упаковки / распаковки

ArrayList ints = new ArrayList();
myInts.Add(1); // boxing
myInts.Add(2); // boxing

int myInt = (int)ints [0]; // unboxing

Console.Write("Value is {0}", myInt); // boxing
1
ответ дан 3 December 2019 в 13:29
поделиться

Одна из ситуаций, когда это происходит, - это, например, если у вас есть метод, который ожидает параметр типа object, и вы передаете один из примитивных типов, например int. Или если вы определяете параметр как 'ref' типа int.

1
ответ дан 3 December 2019 в 13:29
поделиться

Код

int x = 42;
Console.Writeline("The value of x is {0}", x );

фактически упаковывает и распаковывает, потому что Writeline выполняет преобразование int внутрь. Чтобы избежать этого, вы можете сделать

int x = 42;
Console.Writeline("The value of x is {0}", x.ToString());

Остерегайтесь мелких ошибок!

Вы можете объявить свои собственные типы значений, объявив свой собственный тип как struct . Представьте, что вы объявляете структуру с множеством свойств, а затем помещаете несколько экземпляров в ArrayList . Это, конечно, мешает им. Теперь обратитесь к одному из них с помощью оператора [] , приведя его к типу и задайте свойство. Вы просто устанавливаете свойство на копии . Список в ArrayList все еще не изменен.

По этой причине типы значений всегда должны быть неизменными, т. Е.

1
ответ дан 3 December 2019 в 13:29
поделиться
Другие вопросы по тегам:

Похожие вопросы: