2016-04-15 10 views
2
public IList A23 { get; set; } 

s.A23 = new List<int>(new int[] { 62, 63, 64 }); 

IList g = s.A23; 
double d = (double)g[0]; 

Die Doppelbesetzung in der letzten Zeile löst eine Ausnahme aus. g [0] sollte ein Objekt (eines int) sein, das zu einem Double castbar ist.Sollte das nicht funktionieren? (typecast/unboxing)

Ich weiß, dass dies funktioniert:

double d = (double)(int)g[0]; 

Aber das ist nicht meine Frage :). Ich arbeite an einer Laufzeit-Sache, die den Rahmen dieses Beitrags sprengen würde. Da die Quelle eine IList ist, kenne ich den Typ nicht, der dort ist. Ich hätte gedacht, der Compiler könnte das Objekt ohne Unboxing als Int zuerst werfen ??

Antwort

2

Nein, kann es nicht. Unboxing wird nicht gegossen. Sie müssen die Variable entpacken und sie dann umsetzen. In diesem speziellen Fall bedeutet dies zwei Abgüsse.

Wenn Sie die Laufzeit double werfen (nicht der Compiler!) Nicht weiß, wie die object-double zu werfen, und versucht nicht, sie entweder unbox, denn es gibt nichts, was sagt man, dass wollen. In der Tat wäre es vollkommen plausibel, dass Sie die object, und nicht die Box-Variable werden soll. Die Absicht Ihres Codes ist mehrdeutig und die Designer haben sich vielleicht entschieden, sie ganz zu werfen.

+1

Das ist eine plausible Vermutung, aber nicht ganz richtig. Die Mehrdeutigkeit ist hier nicht das eigentliche Problem. –

+0

Ja, als ich sagte "** darf mich entschieden haben" habe ich geraten :) – pid

+0

Sehen Sie, ob Sie und SledgeHammer den eigentlichen Grund für die Einschränkung ausarbeiten können, dass eine Unbox den eigentlichen Typ entpacken muss. (Oder nullable.) –

4

die doppelte Besetzung in der letzten Zeile löst eine Ausnahme

Das ist richtig. Ein boxed T darf nur zu T oder T entpackt werden.

ich der Compiler hätte gedacht, könnte das Objekt ohne Unboxing als int erste

OK werfen, Sie bauen eine Laufzeit, so dass er Charakter bauen für Sie, dies zu erarbeiten. Beschreiben Sie den Code, den Sie erwarten, dass der Compiler ausgibt, daran erinnern, dass der Compiler natürlich nicht weiß, dass ein Int darin ist.

Extrem hilfreicher Hinweis: Wenn das eingerahmte Objekt als dynamische eingegeben wird statt Objekt dann die Umwandlung erfolgreich zu verdoppeln. Das ist (double)(dynamic)(g[0]) funktioniert so, wie Sie es erwarten. "Dynamisch" ist nur "Objekt" mit einem lustigen Hut auf, also warum scheitert man und der andere gelingt?

+0

Ok, also funktioniert die dynamische Besetzung, aber die IL, die sie erzeugt, ist ein wenig zu chaotisch für meine Bedürfnisse. Im Moment mache ich: "emerge call _miItem" um den Gegenstand zu bekommen und dieser Teil funktioniert. Gibt es eine Möglichkeit zu "simulieren", was Dynamik tut. I.e. Nachdem ich _miItem aufgerufen habe, rufe GetType() auf und entpacke dann das Ergebnis des miItems als Ergebnis von GetType()? Scheint wie OpCodes.UnboxAny erfordert einen "hardcoded" Typ? – SledgeHammer

+2

@SledgeHammer: Sie haben festgestellt, dass der generierte Code für das, was Sie wollen, schrecklich ist, und Ihre Frage lautet: "Gibt es einen besseren Weg, es zu tun?" * Wenn ich von einem besseren Weg wüsste, denkst du nicht, dass wir diesen Code erzeugt hätten? * –

+0

@SledgeHammer: Nun, es gibt Dinge, die du hier tun könntest, die eng auf die Tatsache ausgerichtet sind, dass du Casting verdoppelst . Sie könnten zum Beispiel die Methode 'Convert.ToDouble' verwenden. 'dynamic' tut das nicht, weil' dynamic' * tun muss, was der C# -Compiler tun würde * und 'ToDouble' nicht, was der C# -Compiler tut. (https: // msdn.microsoft.com/en-us/library/kx3x7f55(v=vs.110).aspx) –

Verwandte Themen