Frage

Ich habe die folgende Eigenschaft, die eine InvalidCastException warf, wenn der Getter zugegriffen wurde, als ViewState[TOTAL_RECORD_COUNT] null war.

public long TotalRecordCount
{
    get { return (long)(ViewState[TOTAL_RECORD_COUNT] ?? -1); }
    set { ViewState[TOTAL_RECORD_COUNT] = value; }
}

Mein Gedanke ist, dass es falsch das Objekt in ViewState[TOTAL_RECORD_COUNT] zu einem int unbox versucht, die scheiterten, weil es eine long enthalten ist, aber ich denke, es könnte ein Fehler in dieser Logik sein. Ich werde es als Übung dem Leser überlassen, dass Fehler hinweisen.

ich da geändert haben, dass das Eigentum zu lesen

public long TotalRecordCount
{
    get { return (long?)ViewState[TOTAL_RECORD_COUNT] ?? -1; }
    set { ViewState[TOTAL_RECORD_COUNT] = value; }
}

die funktioniert nur anschwellen. Dennoch frage ich mich links, was mit meiner ursprünglichen Version ... Stackoverflow zur Rettung falsch war?

Beachten Sie, dass, wenn ich versuche, (long)(ViewState[TOTAL_RECORD_COUNT] ?? -1) in dem Direkt-Fenster auszuführen, ich die Fehlermeldung Cannot unbox 'ViewState[TOTAL_RECORD_COUNT] ?? -1' as a 'long' bekommen und wenn ich (ViewState[TOTAL_RECORD_COUNT] ?? -1).GetType().Name ausführen ich Int32 bekommen. Ich kann (long)-1 ausführen und mit -1 als Int64 am Ende ... so etwas ist los?

War es hilfreich?

Lösung

Der Rückgabetyp ViewState Indexer ist Object (ich nehme an, Sie ASP.NET Ansichtszustand bedeutet hier). Betrachten wir nun, was der Compiler zu tun hat, wenn er dies sieht (die Code entspricht):

object o = ViewState[...];
var x = o ?? -1;

Es hat den Ergebnistyp des Ausdrucks o ?? -1 irgendwie abzuleiten. Auf der linken Seite sieht er eine object, auf der rechten Seite ein int ist. Offensichtlich ist die allgemeinste Art für diesen Ausdruck auch object. Dies bedeutet jedoch, dass, wenn es tatsächlich endet mit, dass -1 (weil o null war), wird es konvertieren müssen object -. Und für einen int, bedeutet dies, Boxen

So x vom Typ object ist, und es kann eine int enthalten (und vielleicht auch einige andere integrale Art - wir wissen nicht, was in Ihrem Ansichtszustand ist, könnte es short, zum Beispiel). Jetzt schreiben Sie:

long y = (long)x;

Da x object ist, dann ist dies Unboxing. Sie kann jedoch nur unbox Werttypen in genau die gleiche Art (mit der einzigen Ausnahme, dass Sie einen signierten Typen für einen äquivalenten Typen ohne Vorzeichen ersetzen können, und ENUM für den zugrunde liegenden Basistyp). Das heißt, man kann nicht unbox int in long. Ein weitaus einfacher Weg, dies zu repro, ohne „Extra“ Code wäre:

object x = 123;
long y = (long)x;

Welche auch InvalidCastException wirft, und für genau die gleichen Grund.

Andere Tipps

Ein Abguss hat einen Schritt nur sein.

Der Ausdruck <object> ?? <int> produziert ein anderes Objekt, und wenn der erste Wert ist Null, das heißt. ViewState[TOTAL_RECORD_COUNT] null ist, dann wird der resultierende Wert wird in eine Aufgabe, mit einem boxed Int32 sein.

Da kann man kein Objekt unbox ein Int32 auf eine lange enthält, müssen Sie es zunächst zu einem Int32 unbox und warf sie dann auf eine lange.

Die Probleme nicht die Unboxing der ViewState[TOTAL_RECORD_COUNT] sind, das Problem ist die Boxen und Unboxing der -1.

   ViewState[TOTAL_RECORD_COUNT] ?? -1

Sie benutzen die ?? Betreiber auf „Objekt“ und „int“. Die sich ergebende Typ „Objekt“. Das bedeutet, die -1 wird (wie int) eingerahmt werden, wenn das Feld in dem Ansichtszustand nicht vorhanden ist.

Dann wird Ihr Programm stürzt später, wenn es versucht, die (int) -1 als lange unbox.

In Ihrem ursprünglichen, wenn Sie es brechen, das Sie tun:

(ViewState[TOTAL_RECORD_COUNT] ?? -1)

Die null-Koaleszenz-Operator (??) ist specifially entwickelt, um:

  

einen Standardwert für ein Nullable-Wertetypen sowie Referenztypen zu definieren.

In Ihrem Fall, Sie verwenden eine System.Object zu handhaben, so es geht um Ihre „-1“ zu nehmen, behandelt es als Int32, und das Feld in eine neue System.Object. Dann wird versucht, den Int32 in eine langen unbox, die fehlschlägt, da die Besetzung nicht unbox kann und die Art in einem einzigen Schritt ändern.

Sie können dieses Problem lösen leicht durch die Angabe, dass Ihre -1 unter Verwendung des L-Suffix ein lang ist:

public long TotalRecordCount
{
    get { return (long)(ViewState[TOTAL_RECORD_COUNT] ?? -1L); }
    set { ViewState[TOTAL_RECORD_COUNT] = value; }
}

Int64 ist ein Werttyp, so Casting null auf einen Wert Typ wird immer eine Ausnahme (NullReferenceException) werfen. Und ein Int32 zu Int64 Casting erfolgreich sein wird und nicht ein InvalidCastException werfen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top