Frage

Betrachten Sie den folgenden Code ein:

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 Gießen (okay, das dritte ist kein Casting, aber Sie bekommen die Absicht). Welche man bevorzugt werden sollte?

War es hilfreich?

Lösung

string s = (string)o; // 1

InvalidCastException wenn o kein string ist. Andernfalls weist o s, auch wenn o null ist.

string s = o as string; // 2

Ordnet null s wenn o kein string ist oder wenn o ist null. Aus diesem Grunde können Sie es nicht mit Werttypen verwenden (der Bediener nie null in diesem Fall zurückkehren kann). Andernfalls weist o zu s.

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

Verursacht eine wenn Nullreferenceexception o null ist. Ordnet was o.ToString() zurückkehrt, s egal, welche Art o ist.


Verwenden Sie 1 für die meisten Conversions - es ist einfach und unkompliziert. Ich neige dazu, nie 2 fast zu verwenden, da, wenn etwas nicht die richtige Art ist, erwarte ich in der Regel eine Ausnahme auftritt. Ich habe nur eine Notwendigkeit für diese Rückkehr-Null-Typen von Funktionalität mit schlecht gestalteten Bibliotheken, die Fehlercodes verwenden gesehen (z null = Fehler zurück, statt Ausnahmen zu verwenden).

3 ist kein Guss- und ist nur ein Methodenaufruf. Verwenden Sie es, wenn Sie die Zeichenfolgendarstellung eines Nicht-String-Objekt benötigen.

Andere Tipps

  1. string s = (string)o; verwendet, wenn etwas sollte auf jeden Fall sein die andere Sache.
  2. string s = o as string; verwendet, wenn etwas könnte sein, die andere Ding.
  3. string s = o.ToString(); verwenden, wenn Sie interessiert nicht, was es ist aber Sie wollen einfach nur das verwenden verfügbar String-Darstellung.

Es hängt wirklich davon ab, ob Sie wissen, ob o ein String ist und was wollen Sie damit zu tun. Wenn Ihr Kommentar bedeutet, dass o wirklich wirklich ein String ist, würde ich das gerade (string)o Guss bevorzugen -. Es ist unwahrscheinlich, scheitern

Der größte Vorteil der gerade gegossenen ist, dass, wenn es fehlschlägt, erhalten Sie eine InvalidCastException , die Sie ziemlich viel erzählt, was schief gelaufen ist.

Mit dem as Operator, wenn o kein String, s ist auf null, was praktisch ist, wenn Sie sich nicht sicher sind und wollen s testen:

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

Wenn Sie jedoch nicht, dass die Prüfung durchführen, werden Sie s später und haben eine Nullreferenceexception geworfen. Diese neigen dazu, häufiger und ein Los schwieriger aufzuspüren, wenn sie geschieht in der Wildnis aus, da fast jede Zeile dereferenziert eine Variable und eine werfen kann. Auf der anderen Seite, wenn Sie versuchen, auf einen Wert (oder einen beliebigen primitiv oder structs wie Datetime ), müssen Sie die gerade gegossenen verwenden -. die as wird nicht funktionieren

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

Wenn Sie bereits wissen, welche Art es werfen können, verwenden Sie einen C-Casts:

var o = (string) iKnowThisIsAString; 

Beachten Sie, dass nur mit einem C-Casts können Sie explizite Typumwandlung durchführen.

Wenn Sie nicht wissen, ob es die gewünschte Art ist und du gehst, es zu benutzen, wenn es ist, verwenden Sie wie Stichwort:

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

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

Beachten Sie, dass wie wird keine Typumwandlung Betreiber nicht nennen. Es wird nur nicht-null sein, wenn das Objekt nicht null ist und nativ des angegebenen Typs.

Verwenden Sie ToString (), um eine menschenlesbare String-Darstellung eines Objekts zu erhalten, auch wenn es nicht zu bespannen werfen kann.

Das als Schlüsselwort ist gut in asp.net, wenn Sie die Findcontrol-Methode verwenden.

Hyperlink link = this.FindControl("linkid") as Hyperlink;
if (link != null)
{
     ...
}

Dies bedeutet, dass Sie auf der typisierten Variable arbeiten können dann eher dann von object geworfen zu haben, wie Sie es mit einer direkten Besetzung:

object linkObj = this.FindControl("linkid");
if (link != null)
{
     Hyperlink link = (Hyperlink)linkObj;
}

Es ist keine große Sache, aber es spart Zeilen Code und Variablenzuweisung, plus es ist besser lesbar

‚als‘ basierte auf ‚ist‘, das ist ein Schlüsselwort, das zur Laufzeit überprüft, ob das Objekt polimorphycally kompatibel ist (im Grunde, wenn ein Guss gemacht werden kann) und gibt null zurück, wenn die Überprüfung fehlschlägt.

Diese beiden sind äquivalent:

Mit 'als':

string s = o as string;

Mit 'ist':

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

Im Gegenteil, die c-Casts werden auch zur Laufzeit gemacht, aber werfen eine Ausnahme, wenn die Besetzung nicht vorgenommen werden kann.

Nur eine wichtige Tatsache hinzuzufügen:

Das ‚als‘ Schlüsselwort funktioniert nur mit Referenztypen. Sie können nicht tun:

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

In diesen Fällen müssen Sie Gießen verwendet werden.

2 ist nützlich, um zu einem abgeleiteten Typ Gießen.

Nehmen wir an a ist ein Tier:

b = a as Badger;
c = a as Cow;

if (b != null)
   b.EatSnails();
else if (c != null)
   c.EatGrass();

erhalten a mit einem Minimum an Abgüsse zugeführt.

Nach Versuchen auf dieser Seite ausführen: http: / /www.dotnetguru2.org/sebastienros/index.php/2006/02/24/cast_vs_as

(diese Seite wird mit einigen „illegal Referrer“ Fehler auftauchen manchmal, so dass nur aktualisieren, wenn es der Fall ist)

Fazit ist, die „als“ Operator ist in der Regel schneller als ein Guss. Manchmal durch ein Vielfaches schneller, manchmal gerade noch schneller.

I peronsonally Sache „als“ auch besser lesbar ist.

Also, da es schneller und „sicherer“ (wird nicht throw exception) ist, und möglicherweise leichter zu lesen, empfehle ich „als“ die ganze Zeit.

"(string) o" in einer InvalidCastException führen wird, da es keine direkte Besetzung ist.

„o als String“ führt in s eine Nullreferenz zu sein, anstatt eine Ausnahme ausgelöst wird.

„o.ToString ()“ ist kein Guss jeglicher Art per se, es ist eine Methode, die von Objekt implementiert ist und somit in der einen oder anderen, von jeder Klasse in .net, dass „etwas tut“ mit die Instanz der Klasse auf genannt und gibt einen String zurück.

Vergessen Sie nicht, dass String für die Umwandlung gibt es auch ist Convert.ToString (sometype instanceOfThatType), wo sometype eine aus einer Reihe von Arten ist, im Wesentlichen die Gerüste Basistypen.

Alle gegebenen Antworten sind gut, wenn ich etwas hinzufügen möchte: Um direkt String Methoden und Eigenschaften zu verwenden (z ToLower) Sie kann nicht schreiben:

(string)o.ToLower(); // won't compile

Sie können nur schreiben:

((string)o).ToLower();

aber man kann schreiben statt:

(o as string).ToLower();

Die as Option ist besser lesbar (zumindest meiner Meinung nach).

string s = o as string; // 2

Ist bevorzugt, da sie die Leistungseinbuße von Doppelguss vermeiden.

Es scheint, die zwei von ihnen sind vom Konzept her unterschiedlich.

Angießen

Typen müssen nicht unbedingt zusammenhängen. Es kommt in allen Arten von Aromen.

  • Benutzerdefinierte implizites / explizites Casting:. Normalerweise wird ein neues Objekt erstellt wird
  • Wert Typ Implizit: Kopieren ohne Informationen zu verlieren.
  • Wert Typ Explicit:. Kopieren und Informationen können verloren gehen
  • IS-A-Beziehung: Ändern Referenztyp, wirft sonst Ausnahme
  • .
  • Die gleiche Art: 'Casting ist überflüssig'
  • .

Es fühlt sich an wie das Objekt in etwas umgewandelt wird sonst.

AS Operator

Typen haben eine direkte Beziehung. Wie in:

  • Referenzarten:. IS-A-Beziehung Objekte sind immer die gleichen, nur die Referenz Änderungen
  • Werttypen:. Kopieren Boxen und Nullable Types

Es fühlt sich an wie die Sie gehen das Objekt in einer anderen Art und Weise zu handhaben.

Proben und IL

    class TypeA
    {
        public int value;
    }

    class TypeB
    {
        public int number;

        public static explicit operator TypeB(TypeA v)
        {
            return new TypeB() { number = v.value };
        }
    }

    class TypeC : TypeB { }
    interface IFoo { }
    class TypeD : TypeA, IFoo { }

    void Run()
    {
        TypeA customTypeA = new TypeD() { value = 10 };
        long longValue = long.MaxValue;
        int intValue = int.MaxValue;

        // Casting 
        TypeB typeB = (TypeB)customTypeA; // custom explicit casting -- IL:  call class ConsoleApp1.Program/TypeB ConsoleApp1.Program/TypeB::op_Explicit(class ConsoleApp1.Program/TypeA)
        IFoo foo = (IFoo)customTypeA; // is-a reference -- IL: castclass  ConsoleApp1.Program/IFoo

        int loseValue = (int)longValue; // explicit -- IL: conv.i4
        long dontLose = intValue; // implict -- IL: conv.i8

        // AS 
        int? wraps = intValue as int?; // nullable wrapper -- IL:  call instance void valuetype [System.Runtime]System.Nullable`1<int32>::.ctor(!0)
        object o1 = intValue as object; // box -- IL: box [System.Runtime]System.Int32
        TypeD d1 = customTypeA as TypeD; // reference conversion -- IL: isinst ConsoleApp1.Program/TypeD
        IFoo f1 = customTypeA as IFoo; // reference conversion -- IL: isinst ConsoleApp1.Program/IFoo

        //TypeC d = customTypeA as TypeC; // wouldn't compile
    }

Ich möchte die Aufmerksamkeit auf die folgenden Besonderheiten des gewinnen wie Betreiber:

https://docs.microsoft.com / en-us / dotnet / csharp / Sprache Verweis / Keywords / as

  

Beachten Sie, dass die als Operator nur Referenzkonvertierungen durchführt,   Nullable-Conversions und Boxen Konvertierungen. Der als Betreiber kann nicht   führen auch andere Umsetzungen, wie beispielsweise benutzerdefinierte Konvertierungen, die   sollte stattdessen unter Verwendung von Guss Ausdrücke durchgeführt werden.

Beim Versuch, die String-Darstellung von irgendetwas zu bekommen (jeglicher Art), die möglicherweise null sein könnten, ziehe ich die unten stehende Codezeile. Es ist kompakt, es ruft ToString (), und es Griffe richtig nulls. Wenn o null ist, wird s String.Empty enthalten.

String s = String.Concat(o);

Da niemand erwähnte, in der Nähe von instanceOf auf Java nach Stichwort ist dies:

obj.GetType().IsInstanceOfType(otherObj)

Verwenden Sie die direkte Besetzung string s = (string) o; wenn im logischen Kontext Ihrer App string der einzige gültige Typ ist. Mit diesem Ansatz werden Sie InvalidCastException und implementieren das Prinzip der Fehler schnell erhalten. Ihre Logik wird von Passieren des ungültigen Typs weiter oder erhalten Nullreferenceexception geschützt werden, wenn as Operator verwendet wird.

Wenn die Logik verschiedene Arten werfen string s = o as string; erwartet und überprüfen Sie es auf null oder Verwendung is Operator.

New cooles Feature erschien in 7.0 C # Guss zu vereinfachen und die Prüfung ist ein Mustervergleich :

if(o is string s)
{
  // Use string variable s
}

or

switch (o)
{
  case int i:
     // Use int variable i
     break;
  case string s:
     // Use string variable s
     break;
 }

Die folgenden zwei Formen der Typumwandlung (Gießen) in C # unterstützt:

|

(C) v

Konvertieren

• den statischen Typen von v c in dem gegebenen Ausdruck

• Nur möglich, wenn der dynamische Typ von v c, oder einem Subtyp von c

• Wenn nicht, eine InvalidCastException ausgelöst wird,

|

v als C

• Nicht-tödliche Variante (c) v

• So wandelt den statischen Typen von v c in dem gegebenen Ausdruck

• Gibt null zurück, wenn der dynamischen Typ von v ist nicht c oder ein Subtyp von c

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