selectedItem
hat zwei Felder:
int? _cost
string _serialNumber
In diesem Beispiel _cost
und _serialNumber
von selectedItem
sind BEIDE null. Ich lese die Felder selectedItem
über ihre Eigenschaften durch und fülle Textfelder mit ihren Werten aus, wenn ...
TextBox1.Text = selectedItem.Cost.ToString(); //no error
TextBox2.Text = selectedItem.SerialNumber.ToString(); //error
Ich verstehe, dass dies SerialNumber.ToString()
redundant ist (weil es bereits eine Zeichenfolge ist), aber ich verstehe nicht, warum dies diese Ausnahme verursacht:
Das Objekt mit dem Wert "null" braucht einen Wert.
int? _cost
ist nullbar und hat keinen Wert, gibt mir aber keine Ausnahme.string _serialNumber
ist nullbar und hat keinen Wert, aber es gibt mir die Ausnahme.
Diese Frage berührt es, der Typ fragt im Wesentlichen das Gleiche, aber es gibt keine festgelegte Antwort, und sie erklärt auch nicht, warum ein Nullwert int
? Kann ich beispielsweise .ToString()
eine nullfähige int, aber keine null-Zeichenfolge verwenden?
MessageBox.Show
undString.Concat
mitnull
Strings gearbeitet wird.int?
ist ein Werttyp, der aufgerufen wirdNullable<T>
und eine spezielle Behandlung für Nullwerte aufweist.string
ist ein Referenztyp (obwohl ein etwas seltsamer), der tatsächlich einen Wert von haben kannnull
. Ein hatint?
immer einen Wert, es hat nur eine besondere Art zu sagen: "Ich benehme michnull
gerade so."Antworten:
Da der
string
Typnull
wirklich auf nichts zeigt, befindet sich kein Objekt im Speicher.Aber
int?
type (nullable), auch wenn der Wert so eingestellt ist, dass ernull
immer noch auf ein Objekt zeigt.Wenn Sie Jeffrey Richters "CLR via C #" lesen, werden Sie feststellen, dass nullfähige Typen nur Fassadenklassen für gängige Typen mit einigen gekapselten Logiken sind, um die Arbeit mit DB null bequemer zu machen.
Überprüfen Sie msdn , um mehr über nullfähige Typen zu erfahren.
quelle
Nullable<T>
Typ eingefügt .int?
oderInt32?
. NichtInt?
selectedItem.Cost.GetType()
wird , wennCost
der Typ null istint?
. Der Unterschied besteht darin, dassToString
es sich um eine virtuelle Methode handelt, die von überschrieben wirdNullable<T>
und daher direkt aufgerufenint?
werden kann. AndererseitsGetType
ist eine nicht virtuelle Methode für eine Basisklasse vonNullable<T>
(object
tatsächlich) deklariert . Daher muss die Laufzeit denNullable<>
Typ in diesen Klassentyp konvertieren , bevor er aufgerufen werden kann. DiesGetType
wird als Boxen bezeichnet ,Nullable<>
hat jedoch spezielle Boxregeln, sodass eine Nullreferenz erstellt wird.MyNullableBool.ToString
zurückkehrtstring.Empty
und nicht wirft, wennMyNullableBool
null ist.A
Nullable<int>
ist astruct
und kann nicht wirklich null sein. Ein Methodenaufruf für eine "null" -Struktur funktioniert also immer noch.Es gibt etwas "Compiler-Magie", die
_cost == null
einen gültigen Ausdruck macht.quelle
null
zurNullable<T>
Verwendung von normalem C # -Code (dh Überladen von Operatoren) würde erfordern, dass Sie einen Typ aus dem Ausdruck "null
" ableiten können, den Sie nicht ableiten können, da er keinen hat. Der Compiler verwandelt sich im WesentlichenNullable<T> foo = null
inNullable<T> foo = default(Nullable<T>)
undfoo == null
in!foo.HasValue
.int?
ist eigentlich kein Objekt für sich, aber es ist einNullable<int>
Objekt.Wenn Sie also deklarieren
int? _Cost
, deklarieren Sie tatsächlichNullable<int> _Cost
und die Eigenschaft von_Cost.Value
istundefined
nicht das_Cost
Objekt selbst.Laut MSDN :
quelle
_Cost.Value
ist undefiniert, wenn_Cost
null ist (dh wenn_Cost.HasValue
falsch ist)_Cost
Kann nicht wirklich sein,null
da es kein Referenztyp ist.Eine Zeichenfolge ist ein Referenztyp, ein nullfähiges int ist jedoch ein Werttyp. Hier ist eine gute Diskussion der Unterschiede http://www.albahari.com/valuevsreftypes.aspx .
quelle
Die Nullable ist eigentlich eine Struktur, die zwei Eigenschaften verfügbar macht: HasValue und Value. Wenn Sie dies tun, erhalten Sie folgende Fehlermeldung:
int? i = null; i.Value.ToString()
Um zu überprüfen, ob Ihr int? hat einen Wert, auf den Sie zugreifen können
i.HasValue
quelle
NullReferenceException
, sondern einInvalidOperationException
. Siehe Nullable (T) .Value .Ich denke, der Grund dafür ist, dass der Compiler, wenn er auf einen primitiven Datentyp stößt, ihn in das entsprechende Objekt einschließt. Der Methodenaufruf toString () ist hier nur ein indirekter Aufruf (Umschließen und anschließendes Aufrufen der Methode), und die Ausnahme wird dort behandelt. Im Fall von String rufen wir die Methode direkt auf. Wenn die Methode auf eine Null zeigt, löst sie die Ausnahme aus.
quelle
Der Grund ist einfach.
int?
oderNullable<int>
ist eine Struktur oder ein Werttyp , es kann niemals null sein .Was passiert also, wenn wir Folgendes tun:
int? _cost = null;
_cost
wird zwei FelderValue
undHasValue
, wenn wir vergebennull
zu_cost
seinerHasValue
Flagge wird gesetztfalse
und dasValue
Feld zugewiesen würdedefault(T)
im Fallint?
wäre es0
.Nun , wenn wir rufen
ToString
auf_cost
,Nullable<T>
hat eine Überschreibung DefinitionToString
, die , wenn wir betrachten , Microsoft bereitgestellte Quellenreferenz implementiert wie:public override string ToString() { return HasValue ? value.ToString() : ""; }
Somit wird eine leere Zeichenfolge zurückgegeben, da diese
_cost
zugewiesen istnull
.Nun kommt der Fall von
string _serialNumber
. Dastring
es sich um eine Art Referenz und kann rein haltennull
. Wenn es gehalten wird, würde einnull
AufrufToString
wie erwartet die Nullreferenzausnahme erzeugen.Möglicherweise wird Folgendes angezeigt: Werttypen und Referenztypen - MSDN
quelle
TextBox2.Text = selectedItem.SerialNumber.ToString(); //error
yiels Fehler, weil die Funktion ToString () aufgerufen wird, die Mitglied von System.String ist . Diese Funktion gibt diese Instanz von System.String zurück. Es wird keine tatsächliche Konvertierung durchgeführt. String ist auch ein Referenztyp. Ein Referenztyp enthält einen Zeiger auf einen anderen Speicherort, der die Daten enthält.
TextBox1.Text = selectedItem.Cost.ToString(); //no error
gibt keinen Fehler aus, da die Funktion ToString () aufgerufen wird, die Mitglied von System.Integer ist . Diese Funktion konvertiert den numerischen Wert dieser Instanz in die entsprechende Zeichenfolgendarstellung. Integer ist auch ein Werttyp. Ein Datentyp ist ein Werttyp, wenn er die Daten in seiner eigenen Speicherzuordnung enthält.
Der gleiche Funktionsname ToString (), führt jedoch eine andere Aufgabe aus.
String.ToString-Methode
Int32.ToString-Methode
Werttypen und Referenztypen
quelle