2009-08-26 3 views
9

Это кажется ошибка для меня ...C# Автоматические свойства - все еще null после + =?

Я принимаю, что автоматические свойства, определяемые как например:

public decimal? Total { get; set; } 

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

Но даже после установки их значения через + =, это десятичное число? все еще остается нулевым. Поэтому после:

Total += 8; 

Всего по-прежнему не имеет значения. Как это может быть правильно? Я понимаю, что это делает (нуль + 8), но, кажется странным, что он не подхватывает, что это означает, что он должен просто быть установлен на 8 ...

добавлений:

Я сделал «нуль + 8 "в моем вопросе - но заметьте, что он работает со строками. Таким образом, он делает null + «привет» просто отлично и возвращает «привет». Поэтому за кулисами инициализируется строка для строкового объекта со значением «hello». Поведение должно быть одинаковым для других типов, ИМО. Это может быть потому, что строка может принимать значение null в качестве значения, но все же нулевая строка не является инициализированным объектом, правильно?

Может быть, это только потому, что строка не является обнуляемым ...

+7

«Они не были инициализированы, поэтому, конечно, они являются нулевыми». Это суть вашей путаницы. Сначала свойства автоматически назначаются, в этом случае - нулевым. Вы рассуждаете от лжи: свойство не назначено. * Свойство изначально назначено. * В C# нет такой вещи, как «непризнанное свойство». –

+1

Интересное различие. Также интересно, что вы можете найти тысячи примеров людей, ссылающихся на значения «initialized to null» как «uninitialized». Поэтому, возможно, это распространенное заблуждение. Единственное, что мне интересно - если у нас есть эта проблема, когда мы не хотим делать «null + 8 = 8» или «null && true == true», почему это исключение не возникает, когда эти типы вещей сделано? Похоже, что это может помешать некоторым ошибкам отладки. –

ответ

30
public decimal? Total { get; set; } 

Думают о null как «неизвестное значение». Если у вас есть неизвестное количество чего-то, и вы добавите еще 8, сколько у вас сейчас?

Ответ: unknown.

Операция по Nullable переменных

Там являются случаями, когда операции по неизвестных значений дают вам познаваемые результатов.

public bool? State { get; set; } 

Следующие операторы имеют познаваемые решения, даже если они содержат неизвестные значения:

State = null; 
nextState = State & false;   // always equals false 
nextState = State & true;   // still unknown (null) 

nextState = State | true;   // always true 
nextState = State | false;   // still unknown (null) 

увидеть модель?

Конечно, если вы хотитеTotal эквивалентными (равными) 0, когда она null, вы можете использовать нулевой оператор коалесцирующий и написать что-то вроде этого:

Total = (Total ?? 0) + 8; 

Это будет использовать значение Total в вашем уравнении если это не null, в этом случае он будет использовать значение 0.

+0

Да, полагаю, это имеет смысл. Просто кажется фанки. :) –

+0

О, и хороший звонок о коалесцирующем операторе. –

+0

'Total = (Total ?? 0) + 8;' может быть переписано на 'Total = Total.GetValueOrDefault (0) + 8;' в версии .NET 4.5+ –

6
Null + 8 = Null 

Вам необходимо установить его с нуля раньше.

+1

Да, я знаю, это решение, я просто думаю, что это глупо. :) –

+0

почему это глупо? null! = 0 –

+0

Потому что это противоречит интуиции, по крайней мере для меня. Если бы это был мой компилятор, я бы сделал предположение (особенно с чем-то вроде свойства _automatic_), что, если у вас есть неинициализированное значение и вы что-то добавили к нему, он просто подберет добавленную стоимость. Но, возможно, есть случаи, когда такое допущение вызывает проблемы, кто знает. –

5

null означает неизвестное значение,

unknown value + known value = still unknown value 
+0

Я понимаю, что такое null, но мне кажется, что было бы безопасным предположением, что значение null + 8 будет равно 8. Но, я думаю, я просто ошибаюсь. :) –

+0

Вы ошибаетесь в самом деле :) Если 'null' был равен' 0', то в чем смысл «null»? Обратите внимание, что если вы определяете свое свойство как непустой тип (удалить знак '?'), Ему будет присвоено значение по умолчанию для десятичного типа, которое AFAIK равно 0, и вы сможете использовать свой код '+ = 8'. – RaYell

+0

Ха-ха - :) Да, я уже заметил значение по умолчанию с автоподложками. Я не говорю, что нуль должен быть равен нулю, просто если у вас есть инициализированное значение и вы добавляете его в нуль, мне кажется, что поле просто заберет инициализированное значение. –

0

установить значение Total только

Total = 8; 

Я рекомендовал бы читать на Nullable Types, чтобы понять, как они работают. Вы можете проверить, имеет ли свойство значение с помощью HasValue.

MSDN От:

Операторы

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

int? a = 10; 
int? b = null; 

a++;   // Increment by 1, now a is 11. 
a = a * 10; // Multiply by 10, now a is 110. 
a = a + b; // Add b, now a is null. 
+0

Спасибо. Я довольно часто использовал типы с нулевым значением и довольно часто сталкивался с этой проблемой с автоматической инициализацией свойств, но никогда не задавался вопросом, почему. Я предполагаю, что это имеет смысл, хотя я не знаю, сделаю ли я это так ... –

+0

Существует хороший раздел о Nullable Types in C# in Depth, среди других интересных деталей, в основном C# 3, но также немного C# 1 и немного больше на C# 2. Отличная книга. –

+0

Вся идея типов с нулевым значением заключается в том, что вы можете присвоить нулевые значения значениям типов: –

2

От MSDN:

При выполнении сравнения с обнуляемых типов, если значение одного из в обнуляемых типов равна нулю, а другой нет, все сравнения оценивают на false, за исключением! = (не равно). Это важно не предполагать, что , потому что конкретное сравнение возвращает false, противоположный случай возвращает true.

Таким образом, он работает по назначению.

3

Вот один вкладыш для его инициализации по первому зову и увеличить его впоследствии:

public void InitializeOrIncrement(decimal value) 
    { 
     // if Total is null then initialize, otherwise increment 
     Total = (Total == null) ? value : Total + value; 
    } 

    public decimal? Total { get; set; } 
0

Null я sn't то же самое, что и ноль. Ноль плюс восемь восемь ... но нуль плюс восемь? Всегда null. Точно так же, как бесконечность плюс что-то еще бесконечно - это неопределенно.

Вы найдете, что это универсально верно для null. Каждая база данных (по крайней мере, с которой я когда-либо работал) даст вам тот же результат.

+0

Бесконечность + x = бесконечность - хороший способ поставить Это. –

0

общественный десятичный знак?Всего {get; задавать; }

Будет что-то вроде этой работы? Некоторая автоматическая инициализация, если значение еще не установлено.

public decimal? Total 
{ 
    get { return this.totalValue;} 
    set 
    { 
    if(totalValue == null) { this.totalValue = 0;} 
    this.totalValue = value; 
    } 
} 

private decimal? totalValue; 
+0

... но если вы не используете автоматически реализованные свойства, то почему бы просто не инициализировать свое фоновое поле как часть его декларации? 'private decimal? totalValue = 0; ' – STW

+0

Да, давайте посмотрим правде в глаза, единственная причина, по которой я использую автоматические свойства, - это быть ленивым по поводу ввода. (Не набирать текст - просто набирать пальцы!) Если бы я собирался разделить его, я бы просто по умолчанию использовал его 0. –

+0

Yooder, потому что он может не хотеть, чтобы значение было 0, он может пожелать, чтобы оно было нулевым. Роберт, на самом деле, если кто-то устанавливает Total на null, он будет установлен в 0, а затем в этом случае будет сброшен на null, поскольку значение будет иметь значение null. 0 просто используется как ленивый инициализатор. – Ian

1

Я знаю, что это имеет смысл делать

public decimal? Total { get; set; } 

Total = (Total ?? 0) + 8; 

но Wouldnt это просто будет легче сделать:

public decimal Total { get; set; } 

начальное значение Total 0

+0

Да, это на самом деле то, чем я превратил свой код в код. Для текущей работы действительно не имеет смысла, если бы сумма была на самом деле нулевой, если вы думаете об этом. Для элементов, добавляемых в потенциально нулевое значение, имеет смысл, но сумма может, вероятно, всегда быть> = 0. Интересная дискуссия. –

1

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

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

Смежные вопросы