Упаковка / Распаковывающий Типы Nullable - Почему эта реализация?

Замок Windsor является инверсией инструмента управления. Существуют другие как он.

Это может дать Вам объекты с предварительно созданными и предпроводными зависимостями прямо там. весь граф объектов, созданный через отражение и конфигурацию, а не "новый" оператор.

Запускаются здесь: http://tech.groups.yahoo.com/group/altdotnet/message/10434

Предполагает, что у Вас есть электронное письмо, отправляющее класс. EmailSender. Предположите, что у Вас есть другой класс WorkflowStepper. В WorkflowStepper необходимо использовать EmailSender.

Вы могли всегда говорить new EmailSender().Send(emailMessage);

, но что - использование new - создает ПЛОТНОЕ СОЕДИНЕНИЕ, которое трудно изменить. (это, крошечным является изобретенный пример, в конце концов)

Поэтому, что, если, вместо newing этот плохой парень в WorkflowStepper, Вы просто передали его в конструктора?

Таким образом, кто бы ни назвал его, имел к новому EmailSender.

new WorkflowStepper(emailSender).Step()

Предполагают, что у Вас есть сотни этих небольших классов, которые только несут одну ответственность (google SRP).. и Вы используете несколько из них в WorkflowStepper:

new WorkflowStepper(emailSender, alertRegistry, databaseConnection).Step()

Предполагают не вызывать беспокойство о деталях EmailSender, когда Вы пишете WorkflowStepper, или AlertRegistry

Вы просто волнуетесь о беспокойстве, с которым Вы работаете.

Предполагают, что этот целый график (дерево) объектов и зависимостей обеспечен электричеством во ВРЕМЯ ВЫПОЛНЕНИЯ, так, чтобы, когда Вы делаете это:

WorkflowStepper stepper = Container.Get();

Вы получаете реальное соглашение WorkflowStepper со всеми зависимостями, автоматически заполненными, где Вам нужны они.

нет никакого new

, Это всего происходит - потому что это знает то, чему нужно что.

И можно записать меньше дефектов с лучше разработанным, код DRY тестируемым и повторяемым способом.

22
задан Jon Seigel 7 April 2010 в 02:43
поделиться

4 ответа

Я помню, что это поведение было своего рода изменением в последнюю минуту. В ранних бета-версиях .NET 2.0 Nullable был «нормальным» типом значения. Упаковка пустого значения int? превратила его в упакованный int? с логическим флагом. Я думаю, что причина, по которой они решили выбрать нынешний подход, заключается в последовательности. Скажите:

int? test = null;
object obj = test;
if (test != null)
   Console.WriteLine("test is not null");
if (obj != null)
   Console.WriteLine("obj is not null"); 

В первом подходе (box null -> boxed Nullable ) вы не получите "test is not null", но получите " объект не равен нулю », что странно.

Кроме того, если бы они поместили обнуляемое значение в boxed-Nullable :

int? val = 42;
object obj = val;

if (obj != null) {
   // Our object is not null, so intuitively it's an `int` value:
   int x = (int)obj; // ...but this would have failed. 
}

Кроме того, я считаю, что текущее поведение имеет смысл для таких сценариев, как значения базы данных, допускающие обнуление (подумайте, SQL-CLR ... )


Пояснение:

Весь смысл предоставления типов, допускающих значение NULL, состоит в том, чтобы упростить работу с переменными, которые не имеют значимого значения. Они не хотели выделять два разных, не связанных между собой типа. int? должен вести себя более или менее как простой int . Вот почему C # предоставляет поднятые операторы.

Таким образом, при распаковке типа значения в версию, допускающую значение NULL, среда CLR должна выделить объект Nullable , инициализировать поле hasValue значением true и установить для поля значения то же значение, что и в типе значения в штучной упаковке. Это влияет на производительность вашего приложения (выделение памяти во время распаковки).

Это неверно. CLR должна выделить память в стеке для хранения переменной независимо от того, допускает ли она значение NULL. Нет проблем с производительностью при выделении места для дополнительной логической переменной.

23
ответ дан 29 November 2019 в 04:57
поделиться

Думаю, имеет смысл поместить нулевое значение в пустую ссылку. Наличие значения в рамке, говорящего: «Я знаю, что я был бы Int32 , если бы у меня было значение, но нет», мне кажется неинтуитивным. Лучше перейти от версии типа значения «не значение» (значение с HasValue как false) к версии ссылочного типа «не значение» (пустая ссылка)

Я считаю это изменение было внесено на основании отзывов сообщества, кстати.

Это также позволяет интересно использовать как даже для типов значений:

object mightBeADouble = GetMyValue();

double? unboxed = mightBeADouble as double?;
if (unboxed != null)
{
    ...
}

Это больше соответствует способу "неопределенных преобразований" обрабатывается со ссылочными типами, чем предыдущий:

object mightBeADouble = GetMyValue();

if (mightBeADouble is double)
{
    double unboxed = (double) mightBeADouble;
    ...
}

(Он также может работать лучше, поскольку существует только одна проверка типа времени выполнения.)

9
ответ дан 29 November 2019 в 04:57
поделиться

Благодаря такому поведению вы получаете то, что коробочная версия реализует все интерфейсы, поддерживаемые базовым типом. (Цель состоит в том, чтобы сделать Nullable таким же, как int для всех практических целей.) Упаковка в boxed-Nullable вместо boxed-int предотвратит такое поведение.

Со страницы MSDN,

double? d = 44.4;
  object iBoxed = d;
  // Access IConvertible interface implemented by double.
  IConvertible ic = (IConvertible)iBoxed;
  int i = ic.ToInt32(null);
  string str = ic.ToString();

Также просто получить int из коробочной версии Nullable - обычно вы не можете распаковать в тип, отличный от исходного src тип.

float f = 1.5f;
object boxed_float = f;
int int_value = (int) boxed_float; // will blow up. Cannot unbox a float to an int, you *must* unbox to a float first.

float? nullableFloat = 1.4f;
boxed_float = nullableFloat;
float fValue = (float) boxed_float;  // can unbox a float? to a float    Console.WriteLine(fValue);

Здесь вам не нужно знать, была ли исходная версия int или Nullable. (+ вы тоже получаете некоторую производительность; сэкономьте место для хранения логического значения hasValue , а также в объекте в коробке)

5
ответ дан 29 November 2019 в 04:57
поделиться

Думаю, это в основном то, что он делает. Приведенное описание включает ваше предложение (т. Е. Упаковка в Nullable ).

Кроме того, после упаковки устанавливается поле hasValue .

0
ответ дан 29 November 2019 в 04:57
поделиться
Другие вопросы по тегам:

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