2009-02-26 3 views
8

Я видел это в устаревшем коде и в некоторых проектах с открытым исходным кодом .NET. Я не могу представить себе причину этого. Просто использование «null» кажется мне намного легче.Почему люди используют магические значения вместо нуля в своем коде?

Пример:

public class Category 
{ 
    int parentID; 

    bool HasParent 
    { 
     get 
     { 
      return parentID != -1; 
     } 
    } 
} 

против

public class Category 
{ 
    int parentID; 

    bool HasParent 
    { 
     get 
     { 
      return parentID != null; 
     } 
    } 
} 
+0

Вы бы сделали намного лучше, если бы показали хотя бы пример. – GEOCHET

+0

-1: нет кода. -1: нет проблем. В чем проблема? Что не работает? –

+0

Вы отменили проверку (должен быть parentID! = Null), но я думаю, что вопрос действительно. +1 – erikkallen

ответ

0

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

+0

Да, они хранятся в одном месте с символическим значением, например Null.NullInteger и Null.NullDate, но я не мог понять, почему он полезен – Paco

+0

Тогда это вовсе не «волшебное значение» - магические значения - это литералы в исходном коде, которые не имеют контекста и, следовательно, двусмысленного смысла. –

+0

Я считаю это магическим значением, потому что вы должны знать, что это не просто целое число или дата, но вы должны сравнить его с Null.NullObject, чтобы знать, что это значит. Вы не можете знать, что вам нужно сравнить его с nullobject перед использованием значения. – Paco

3

Наличие нулевого объекта может вызвать исключения, тогда как коды ошибок (например, случай сбоя «-1») не будут вызывать исключение.

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

2

Работая над большими хранилищами данных, я иногда использую значение 0 вместо этого, если null, для вставки ненулевого значения в мой куб. У меня всегда есть 0 id, соответствующий значению «Неизвестно» во всех измерениях, поэтому у меня есть куб без нулевых значений.

главный интерес к ней, чтобы проще и более эффективные запросы

4

Они часто привычки разработаны при программировании на языке C. Многие C программист будет horified на отходах обнуляемого Интс, что, по крайней мере, требуют всего дополнительного бита и, возможно, даже указателя. Это особенно плохо, когда вы знаете, что значение будет положительным, и у вас есть все пространство отрицательных значений для использования для флагов. -1 может означать не задано, -2 может означать, что parentId даже не имеет смысла в контексте этого узла, -3 может означать, что у узла был родитель, который не мог справиться с работой и остался на выпивке и никогда не виделась снова и т. д.

В мире C# чистка нулевых ints (и их простая интеграция с RDMS) вместе с компьютерами с 2 ГБ + ОЗУ означает, что старые привычки C медленно умирают, но старые привычки живучи.

1

Ненасыщенные типы значений недоступны на каждом языке/окружающей среде; Они были добавлены в .Net 2.0. Если ваш устаревший код основан на .Net и был запущен с использованием инфраструктуры 1.1, тогда ваш ответ заключается в том, что в то время значение null не было вариантом.

11

Поскольку для значения «null» тип должен иметь значение NULL. Это хорошо работает для ссылочных типов (любого класса вы определяете и стандартную библиотеку), и если вы посмотрите, вы увидите, что люди сделать использовать нуль всякий раз, когда они имеют эталонный объект без значения

Employee employee = Employees.Find("John Smith"); 
if(employee == null) throw new Exception("Employee not found"); 

Этого вопрос приходит, когда вы используете значение типа типа int, char или float. В отличие от ссылочных типов, которые указывают на блок данных где-то еще в памяти, эти значения хранятся и обрабатываются inline (нет указателя/ссылки).

Из-за этого значения типов не имеют нулевого значения. В коде, который вы указали, это невозможно для parentID быть нулевым (я действительно удивлен, что это даже получено вашим компилятором - Visual Studio 2008 и, вероятно, 2005 будет рисовать зеленую подчеркивание и сказать вам, что инструкция всегда ложна) ,

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

int? parentID; 

Теперь ParentID может содержать нулевое значение, потому что теперь указателя (хорошо " reference ") к 32-битовому целому, а не просто 32-битовому целому.

Так что, надеюсь, вы понимаете, почему «магические значения» часто используются для представления нуля базовыми типами (типами значений). Это просто много неприятностей, и часто бывает большой успех (найдите, что такое бокс/распаковка), чтобы сохранить эти типы значений в качестве ссылки на значение, чтобы позволить им быть нулевыми.

Edit: Для получения дополнительной справки о боксе/распаковка (то, что вам нужно иметь Int == NULL), смотрите в статье MSDN:

бокса и распаковка (C# Руководство по программированию)

Эксплуатационные характеристики

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

+0

Я не могу представить случая, когда это очень небольшое усиление производительности имеет решающее значение. – Paco

+2

Накладные расходы * не маленькие * - вы говорите о добавлении операций по боксу/распаковке к * fundimental * типам данных и операциям. Тест, выполняющий операцию сложения условного целого, выполняется в 9 раз медленнее, когда значения являются нулевыми из-за накладных расходов бокса. Попробуйте сами. – David

+0

Я знаю, сколько времени требуется, но я не верю в оптимизацию алгоритмов O (N). – Paco

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