2009-02-26 6 views
8

Ich habe das in Legacy-Code und in einigen .NET-Open-Source-Projekten gesehen. Ich kann mir keinen Grund vorstellen, dies zu tun. Nur "Null" zu benutzen, scheint mir viel einfacher zu sein.Warum verwenden Menschen magische Werte anstelle von null in ihrem Code?

Beispiel:

public class Category 
{ 
    int parentID; 

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

gegen

public class Category 
{ 
    int parentID; 

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

Sie würden viel besser tun, wenn Sie mindestens ein Beispiel zeigten. – GEOCHET

+0

-1: kein Code. -1: kein Problem. Was ist das Problem? Was funktioniert nicht? –

+0

Sie haben die Prüfung rückgängig gemacht (sollte parentID sein! = Null), aber ich denke, die Frage ist gültig. +1 – erikkallen

Antwort

0

Haben Sie wirklich in die Anwendung sah zu sehen? Solange die magische Zahl an einem einzigen Ort mit einem beschreibenden Namen gespeichert ist, kann sie sehr nützlich sein.

+0

Ja, sie sind an einem einzigen Ort mit einem beschreibenden Wert, wie Null.NullInteger und Null.NullDate, aber ich konnte nicht herausfinden, warum es nützlich ist – Paco

+0

Dann ist es überhaupt kein "magischer Wert" - Magische Werte sind Literale im Quellcode, die keinen Kontext und daher mehrdeutige Bedeutung haben. –

+0

Ich halte dies für einen magischen Wert, weil Sie wissen müssen, dass es nicht nur eine Ganzzahl oder ein Datum ist, sondern Sie müssen es mit dem Null.NullObject vergleichen, um zu wissen, was es bedeutet. Sie können nicht wissen, dass Sie es mit dem Nullobjekt vergleichen müssen, bevor Sie den Wert verwenden. – Paco

3

Wenn ein Null-Objekt vorhanden ist, können Ausnahmen ausgelöst werden, während Fehlercodes (wie ein "-1" -Fehlerfall) keine Ausnahme auslösen.

Dies kann in Sprachen oder Anwendungen, die Ausnahmen nicht gut behandeln, kritisch sein.

2

Wenn ich an großen Datawarehouses arbeite, benutze ich manchmal den 0-Wert, wenn null, um einen Nicht-Null-Wert in meinen Cube einzufügen. Ich habe immer eine ID 0, die dem Wert 'Unbekannt' in allen Dimensionen entspricht, also habe ich einen Würfel ohne Nullwerte.

das Hauptinteresse darin ist simplier zu haben und effizientere Abfragen

4

Diese werden oft entwickelt Gewohnheiten, wenn sie in C. Programmieren eines Viel C-Programmierer an der Verschwendung von Nullable-Ints horified würde, die zumindest erfordern ein ganzes zusätzliches Bit und möglicherweise sogar einen Zeiger. Dies ist besonders schlimm, wenn Sie wissen, dass der Wert positiv ist und Sie den gesamten Raum mit negativen Werten für Flags verwenden. -1 kann bedeuten, nicht gesetzt, -2 kann bedeuten, dass parentId im Kontext dieses Knotens nicht einmal Sinn ergibt, -3 kann bedeuten, dass der Knoten ein Elternteil hatte, das mit der Arbeit nicht umgehen konnte und auf einem Trinkgelage blieb und wurde nie wieder gesehen, etc ...

In der C# Welt die Reinheit von Nullable Ints (und ihre einfache Integration mit RDMS) zusammen mit Computern mit 2GB + RAM bedeutet, dass die alten C Gewohnheiten langsam sterben, aber alte Gewohnheiten Stirb langsam.

1

Nullable-Werttypen sind nicht in jeder Sprache/Umgebung verfügbar. Sie wurden zu .Net 2.0 hinzugefügt. Wenn Ihr Legacy-Code .Net-basiert ist und mit dem 1.1-Framework gestartet wurde, lautet Ihre Antwort, dass null zu der Zeit keine Option war.

11

Da ein "Null" -Wert vorhanden sein muss, muss der Typ nullfähig sein. Dies funktioniert für Referenztypen in Ordnung (jede Klasse, die Sie definieren und die Standard-Bibliothek), und wenn Sie schauen Sie werden sehen, dass die Menschen tun Verwendung null, wenn sie ein Referenzobjekt ohne Wert haben

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

Die Frage kommt, wenn Sie den Wert Typen wie Int, Char oder Float verwenden. Im Gegensatz zu Referenztypen, die auf einen Datenblock irgendwo anders im Speicher zeigen, werden diese Werte inline gespeichert und manipuliert (es gibt keinen Zeiger/Verweis).

Aus diesem Grund haben die Werttypen standardmäßig keinen Nullwert. In dem von Ihnen angegebenen Code ist es unmöglich für ParentID null zu sein (Ich bin überrascht, dass dies sogar von Ihrem Compiler - Visual Studio 2008 und wahrscheinlich 2005 wird eine grüne Unterstreichung ziehen und Ihnen sagen, dass die Aussage immer falsch ist) .

Damit ein int einen Nullwert zu haben, müssen Sie es erklären, wie NULL festlegbare

int? parentID; 

Jetzt parentID einen Nullwert enthalten kann, weil sie jetzt ein Zeiger (gut ist " Referenz ") zu einer 32-Bit-Ganzzahl statt nur einer 32-Bit-Ganzzahl.

Also hoffentlich verstehen Sie, warum "magische Werte" oft verwendet werden, um null mit den grundlegenden Typen (Werttypen) darzustellen. Es ist einfach eine Menge Ärger und oft ein großer Leistungseinbruch (Nachschlagen was Boxen/Unboxing ist), diese Werttypen als Referenz auf den Wert zu speichern, damit sie null sein können.

Edit: Für weitere Referenz über Boxen/Unboxing (was Sie einen int == null haben müssen), den Artikel zu einem MSDN:

Boxen und Unboxing (C# -Programmierhandbuch)

Leistung

In Bezug auf einfache Zuordnungen sind Boxen und Unboxing rechenintensive Prozesse. Wenn ein Werttyp eingerahmt ist, muss ein neues Objekt zugewiesen und aufgebaut werden. In geringerem Maße ist die zum Unboxing erforderliche Besetzung auch rechnerisch aufwändig. Weitere Informationen finden Sie unter Leistung.

+0

Ich kann mir keinen Fall vorstellen, in dem dieser sehr kleine Leistungsgewinn kritisch ist. – Paco

+2

Der Overhead ist * nicht klein * - Sie sprechen über das Hinzufügen von Boxen/Unboxing-Operationen zu den * fundimental * Datentypen und Operationen. Ein Benchmark, der eine bedingte Ganzzahladdition ausführt, wird 9 Mal langsamer ausgeführt, wenn die Werte aufgrund des Boxing-Overhead nullbar sind. Probieren Sie es selbst aus. – David

+0

Ich weiß wie lange es dauert, aber ich glaube nicht an die Optimierung von O (N) Algorithmen. – Paco