869 Stimmen

Direktes Gießen vs. "als"-Operator?

Betrachten Sie den folgenden Code:

void Handler(object o, EventArgs e)
{
   // I swear o is a string
   string s = (string)o; // 1
   //-OR-
   string s = o as string; // 2
   // -OR-
   string s = o.ToString(); // 3
}

Was ist der Unterschied zwischen den drei Arten von Güssen (okay, der dritte ist kein Guss, aber Sie verstehen die Absicht). Welche sollte bevorzugt werden?

1027voto

Sander Punkte 24565
string s = (string)o; // 1

Wirft InvalidCastException si o ist kein string . Andernfalls ordnet o a s auch wenn o es null .

string s = o as string; // 2

Weist zu. null a s si o ist keine string oder wenn o es null . Aus diesem Grund können Sie ihn nicht mit Werttypen verwenden (der Operator könnte niemals null in diesem Fall). Andernfalls ordnet o a s .

string s = o.ToString(); // 3

Verursacht eine NullReferenceException si o es null . Weist zu, was auch immer o.ToString() kehrt zurück zu s gleich welcher Art o ist.


Verwenden Sie 1 für die meisten Umrechnungen - das ist einfach und unkompliziert. Ich neige dazu, fast nie 2 verwenden, da, wenn etwas nicht der richtige Typ ist, ich in der Regel erwarten, dass eine Ausnahme auftritt. Ich habe nur gesehen, eine Notwendigkeit für diese return-null Art von Funktionalität mit schlecht gestalteten Bibliotheken, die Fehlercodes verwenden (z. B. return null = Fehler, anstatt mit Ausnahmen).

3 ist kein Cast, sondern nur ein Methodenaufruf. Verwenden Sie ihn, wenn Sie die String-Darstellung eines Nicht-String-Objekts benötigen.

430voto

Quibblesome Punkte 24734
  1. string s = (string)o; Verwenden Sie, wenn etwas sollte definitiv die andere Sache sein.
  2. string s = o as string; Verwenden Sie, wenn etwas sein könnte die andere Sache.
  3. string s = o.ToString(); Verwenden Sie es, wenn es Ihnen egal ist, was es ist, sondern Sie einfach die verfügbare String-Darstellung verwenden.

35voto

Blair Conrad Punkte 217777

Es hängt wirklich davon ab, ob Sie wissen, ob o ist eine Zeichenkette und was Sie damit machen wollen. Wenn Ihr Kommentar bedeutet, dass o wirklich ein String ist, würde ich den geraden bevorzugen (string)o Es ist unwahrscheinlich, dass er scheitert.

Der größte Vorteil des geraden Wurfs ist, dass man bei einem Fehlschlag eine InvalidCastException was Ihnen ziemlich genau sagt, was schief gelaufen ist.

Mit dem as Betreiber, wenn o keine Zeichenkette ist, s wird eingestellt auf null was praktisch ist, wenn Sie unsicher sind und testen wollen s :

string s = o as string;
if ( s == null )
{
    // well that's not good!
    gotoPlanB();
}

Wenn Sie diesen Test jedoch nicht durchführen, werden Sie s später und haben eine NullReferenceException geworfen. Diese sind in der Regel häufiger und ein Los schwerer aufzuspüren, wenn sie erst einmal in freier Wildbahn vorkommen, da fast jede Zeile eine Variable dereferenziert und eine auslösen kann. Andererseits, wenn Sie versuchen, auf einen Werttyp zu casten (irgendeine Primitive oder Strukturen wie DateTime ), müssen Sie den geraden Wurf verwenden - die as wird nicht funktionieren.

Im speziellen Fall der Konvertierung in eine Zeichenkette hat jedes Objekt eine ToString Ihre dritte Methode kann also in Ordnung sein, wenn o nicht null ist und Sie denken, dass die ToString Methode könnte das tun, was Sie wollen.

11voto

Sergio Acosta Punkte 11210

As" basiert auf "is", einem Schlüsselwort, das zur Laufzeit prüft, ob das Objekt polimorphologisch kompatibel ist (im Grunde genommen, ob ein Cast durchgeführt werden kann) und null zurückgibt, wenn die Prüfung fehlschlägt.

Diese beiden sind gleichwertig:

Verwendung von 'als':

string s = o as string;

Verwendung von 'ist':

if(o is string) 
    s = o;
else
    s = null;

Im Gegensatz dazu wird der c-style cast auch zur Laufzeit durchgeführt, löst aber eine Ausnahme aus, wenn der cast nicht durchgeführt werden kann.

Ich möchte nur eine wichtige Tatsache hinzufügen:

Das Schlüsselwort "as" funktioniert nur bei Referenztypen. Sie können das nicht tun:

// I swear i is an int
int number = i as int;

In diesen Fällen müssen Sie den Guss verwenden.

10voto

Mark Cidade Punkte 95914

Wenn Sie bereits wissen, in welchen Typ er casten kann, verwenden Sie einen Cast im C-Stil:

var o = (string) iKnowThisIsAString; 

Beachten Sie, dass Sie nur mit einem Cast im Stil von C eine explizite Typüberwindung durchführen können.

Wenn Sie nicht wissen, ob es sich um den gewünschten Typ handelt und Sie ihn in diesem Fall verwenden wollen, verwenden Sie als Stichwort:

var s = o as string;
if (s != null) return s.Replace("_","-");

//or for early return:
if (s==null) return;

Beachten Sie, dass als ruft keine Typumwandlungsoperatoren auf. Es ist nur dann nicht-null, wenn das Objekt nicht null ist und von Natur aus vom angegebenen Typ ist.

Verwenden Sie ToString(), um eine menschenlesbare String-Darstellung eines beliebigen Objekts zu erhalten, auch wenn es nicht in String umgewandelt werden kann.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X