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?

8voto

Glenn Slaven Punkte 32691

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

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

Das bedeutet, dass Sie mit der typisierten Variablen arbeiten können, anstatt sie von object wie bei einem direkten Wurf:

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

Es ist keine große Sache, aber es spart Codezeilen und Variablenzuweisungen, und es ist lesbarer

8voto

Brady Moritz Punkte 8258

Nach den auf dieser Seite durchgeführten Experimenten: http://www.dotnetguru2.org/sebastienros/index.php/2006/02/24/cast_vs_as

(auf dieser Seite werden manchmal "illegale Referrer"-Fehler angezeigt, also aktualisieren Sie einfach, wenn dies der Fall ist)

Die Schlussfolgerung ist, dass der "as"-Operator normalerweise schneller ist als ein Cast. Manchmal um ein Vielfaches schneller, manchmal nur knapp schneller.

Ich denke, dass "als" auch besser lesbar ist.

Da es sowohl schneller als auch "sicherer" ist (es wird keine Ausnahme ausgelöst) und möglicherweise einfacher zu lesen, empfehle ich, immer "as" zu verwenden.

6voto

Joel in Gö Punkte 7212

2 ist nützlich für das Casting auf einen abgeleiteten Typ.

Angenommen, 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 Würfen gefüttert.

6voto

Lucas Teixeira Punkte 694

Es scheint, als ob die beiden konzeptionell unterschiedlich sind.

Direktes Gießen

Typen müssen nicht unbedingt miteinander verbunden sein. Es gibt sie in allen möglichen Geschmacksrichtungen.

  • Benutzerdefiniertes implizites/explizites Casting: Normalerweise wird ein neues Objekt erstellt.
  • Wert Typ Implizit: Kopieren ohne Informationsverlust.
  • Werttyp explizit: Kopien und Informationen könnten verloren gehen.
  • IS-A-Beziehung: Referenztyp ändern, sonst wird eine Ausnahme ausgelöst.
  • Gleicher Typ: Casting ist überflüssig".

Es fühlt sich an, als würde das Objekt in etwas anderes umgewandelt werden.

AS-Betreiber

Typen haben eine direkte Beziehung. Wie in:

  • Referenztypen: IS-A-Beziehung Die Objekte sind immer dieselben, nur der Verweis ändert sich.
  • Werttypen: Kopieren Boxen und löschbare Typen.

Es fühlt sich an, als würden Sie das Objekt auf eine andere Weise behandeln.

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
    }

5voto

Rob Punkte 44368

"(string)o" führt zu einer InvalidCastException, da es keinen direkten Cast gibt.

"o as string" führt dazu, dass s eine Null-Referenz ist, anstatt dass eine Ausnahme ausgelöst wird.

"o.ToString()" ist kein Cast per se, sondern eine Methode, die von object und damit auf die eine oder andere Weise von jeder Klasse in .net implementiert wird, die mit der Instanz der Klasse, von der sie aufgerufen wird, "etwas tut" und eine Zeichenkette zurückgibt.

Vergessen Sie nicht, dass es für die Umwandlung in eine Zeichenkette auch Convert.ToString(someType instanceOfThatType) gibt, wobei someType einer aus einer Reihe von Typen ist, im Wesentlichen die Basistypen des Frameworks.

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