Свойство Now выглядит примерно так:
DateTime Now {
get {
// Get the OS time
return new DateTime(year, month, day, hour, min, sec...)
}
}
(технически неверно, Now теперь внутренне вызывает UtcNow, который вызывает ОС :-), но вы поняли идею).
DateTime.Now является фабрикой для DateTime: -)
В общем, вам обычно следует избегать упаковки ваших типов значений.
Однако в редких случаях это полезно. Например, если вам нужно настроить таргетинг на платформу 1.1, у вас не будет доступа к общим коллекциям. Любое использование коллекций в .NET 1.1 потребует обработки вашего типа значения как System.Object, что вызывает упаковку / распаковку.
Еще есть случаи, когда это может быть полезно в .NET 2.0+. Каждый раз, когда вы хотите воспользоваться преимуществом того факта, что все типы, включая типы значений, можно рассматривать как объект напрямую, вам может потребоваться использовать упаковку / распаковку. Иногда это может быть удобно, поскольку позволяет сохранять любой тип в коллекции (используя объект вместо T в общей коллекции), но в целом этого лучше избегать, поскольку вы теряете безопасность типов.
Практически никогда не бывает веских причин для преднамеренной упаковки типа значения. Почти всегда причина для упаковки типа значения состоит в том, чтобы сохранить его в некоторой коллекции, которая не поддерживает типы. Старый ArrayList , например, представляет собой набор объектов, которые являются ссылочными типами. Единственный способ собрать, скажем, целые числа - это упаковать их как объекты и передать их в ArrayList.
В настоящее время у нас есть общие коллекции, так что это не проблема.
Упаковка обычно происходит автоматически в .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), который обрабатывает все как {объект}, не зависящий от типа. Это добавляет еще одну причину использования общих коллекций,
Я бы порекомендовал вам 2 хорошие статьи Эрика Липперта
http://blogs.msdn.com/ericlippert/archive/2009/04/27/the-stack-is-an -implementation-detail.aspx
Здесь это цитата, с которой я согласен на 100%
Использование стека для локальных значений значения тип - это просто оптимизация, CLR действует от вашего имени. Соответствующая особенность типов значений: что у них есть семантика бытия копируется по значению, не то чтобы иногда их освобождение может быть оптимизировано время выполнения.
В 99% приложений разработчики не должны заботиться о том, почему типы значений находятся в стеке, а не в куче, и какой прирост производительности мы можем здесь получить. Juts имеет в виду очень простые правила:
Любые правила разрешают исключения в особых случаях, но не пытайтесь чрезмерно оптимизировать.
ps Я встретил некоторых разработчиков ASP.NET с 2-3-летним опытом, которые не знают разницы между стеком и кучей. :-( Я бы не стал нанимать такого человека, если бы я был интервьюером, но не потому, что упаковка / распаковка может быть узким местом на любом из сайтов ASP.NET, которые я когда-либо видел.
Я думаю, что хороший пример бокса в C # встречается в неуниверсальных коллекциях, таких как ArrayList .
Одним из примеров может быть случай, когда метод принимает параметр объекта, а тип значения должен быть передан.
Ниже приведены некоторые примеры упаковки / распаковки
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
Одна из ситуаций, когда это происходит, - это, например, если у вас есть метод, который ожидает параметр типа object, и вы передаете один из примитивных типов, например int. Или если вы определяете параметр как 'ref' типа int.
Код
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
все еще не изменен.
По этой причине типы значений всегда должны быть неизменными, т. Е.