Casting und Verwendung des Schlüsselworts 'as' in der CLR
Bei der Programmierung von Schnittstellen, die ich gefunden habe, mache ich viel Gießen oder Objekttyp-Konvertierung.
Gibt es einen Unterschied zwischen diesen zwei Methoden der Umstellung? Wenn ja, gibt es einen Kosten-Unterschied bzw. wie wirkt sich das auf mein Programm?
public interface IMyInterface
{
void AMethod();
}
public class MyClass : IMyInterface
{
public void AMethod()
{
//Do work
}
//Other helper methods....
}
public class Implementation
{
IMyInterface _MyObj;
MyClass _myCls1;
MyClass _myCls2;
public Implementation()
{
_MyObj = new MyClass();
//What is the difference here:
_myCls1 = (MyClass)_MyObj;
_myCls2 = (_MyObj as MyClass);
}
}
Auch, was "im Allgemeinen" die bevorzugte Methode?
Kommentar zu dem Problem - Öffnen
Könntest du ein kleines Beispiel dafür, warum bist du mit dem wirft in Erster Linie die Frage, oder vielleicht einen neuen zu starten? Ich bin irgendwie interessiert, warum würden Sie brauchen, die Besetzung für unit-Tests nur. Ich denke, es ist außerhalb des Umfangs dieser Frage, obwohl.
Ich kann wohl meine unit-test, um dies zu verhindern, müssen für diese. Im Grunde läuft es auf die Tatsache, dass ich eine Immobilie auf meine konkrete Objekt, das nicht in die Schnittstelle. Ich brauche, um das Eigentum, sondern das wirkliche Leben, die Eigenschaft hätte, die von anderen bedeutet. Nicht, dass die Antwort auf Ihre Frage?
Als Patrik Hägne scharfsinnig Punkte unten, es WIRD einen Unterschied.
InformationsquelleAutor der Frage Frank V | 2009-01-30
Du musst angemeldet sein, um einen Kommentar abzugeben.
Die Antwort unter die Linie geschrieben wurde, im Jahr 2008.
C# 7 eingeführt, pattern-matching, die weitgehend ersetzt die
as
Betreiber, da kann man jetzt schreiben:Beachten Sie, dass
tt
ist noch im Rahmen, nachdem diese, aber nicht definitiv zugewiesen. (Es ist definitiv zugeordnet, die innerhalb derif
Körper.) Das ist etwas ärgerlich, in einigen Fällen, so wenn Sie wirklich über die Einführung der kleinsten Anzahl von Variablen möglich, in jedem Bereich, die Sie vielleicht noch nutzen möchtenis
gefolgt von einer Besetzung.Ich glaube nicht, dass die Antworten so weit (zum Zeitpunkt der Beginn dieser Antwort!) haben wirklich erklärt wird wo es sich lohnt mit denen.
Nicht tun:
Dies ist nicht nur die überprüfung zweimal, aber es kann die überprüfung verschiedener Dinge, wenn
randomObject
ist ein Feld, anstatt eine lokale variable. Es ist möglich für die "wenn" zu übergeben, aber dann ist der cast fehl, wenn ein anderer thread, ändert sich der Wert vonrandomObject
zwischen den beiden.Wenn
randomObject
wirklich sollte eine Instanz vonTargetType
ist, D. H. wenn es ist nicht, bedeutet, dass es ein bug ist, dann ist der Guss die richtige Lösung. Das wirft eine Ausnahme sofort, was bedeutet, dass keine weitere Arbeit erfolgt unter falschen Annahmen beruhen, und die Ausnahme korrekt zeigt die Art der Fehler.Wenn
randomObject
könnte eine Instanz vonTargetType
undTargetType
ist ein Referenz-Typ, dann verwenden Sie code wie diesen:Wenn
randomObject
könnte eine Instanz vonTargetType
undTargetType
ist ein Werttyp, dann können wir Sie nicht verwendenas
mitTargetType
selbst, aber wir können eine nullable-Typ:(Hinweis: derzeit ist dies tatsächlich langsamer als + cast. Ich denke, es ist mehr elegant und konsistent, aber es wir gehen.)
Wenn Sie wirklich nicht brauchen, wird der umgewandelte Wert, aber Sie müssen nur wissen, ob es ist eine Instanz von TargetType, dann die
is
- operator ist dein Freund. In diesem Fall ist es egal, ob TargetType ist ein Verweistyp oder ein Werttyp ist.Möglicherweise gibt es andere Fälle, in denen Generika wo
is
nützlich ist (vielleicht, weil Sie nicht wissen, ob T ein Referenztyp oder nicht, so können Sie nicht benutzen) aber Sie sind relativ vage.Bin ich fast sicher verwendet werden
is
für den Wert geben Sie den Fall nun vor, nicht mit Gedanke, mit einem nullable-Typ undas
zusammen 🙂EDIT: Beachten Sie, dass keines der oben genannten Gespräche über Leistung, andere als die Wert-Typ Fall, wo habe ich festgestellt, dass unboxing, um eine null-value Typ ist wirklich langsamer - aber konsequent.
Als pro naasking Antwort -, ist-und-Darsteller-oder ist-und-wie sind die beiden so schnell wie wie-und-null-check mit modernen JITs, wie gezeigt, durch den folgenden code:
Auf meinem laptop, alle diese führen in etwa 60ms. Zwei Dinge zu beachten:
Lassen Sie uns also keine sorgen über die Leistung. Kümmern wir uns also über die Richtigkeit und Konsistenz.
Ich behaupte, dass ist-und-cast (oder-und -) sind beide unsicher beim Umgang mit Variablen, wie die Art des Wertes bezieht, es kann sich ändern, wegen einem anderen thread zwischen dem test und dem cast. Das wäre eine ziemlich seltene situation - aber ich hätte lieber eine Konvention, die ich verwenden können, konsequent.
Ich behaupte auch, dass die als-dann-null-check ermöglicht eine bessere Trennung von Bedenken. Wir haben eine Anweisung, die versucht, eine Umwandlung, und dann noch eine Anweisung, die verwendet das Ergebnis. Die ist-und-Darsteller-oder ist-und-wie führt einen test und dann ein weiterer Versuch, konvertieren Sie den Wert.
Anders ausgedrückt, würde jemand immer schreiben:
Dass die Art dessen, was ist-und-Darsteller zu tun - obwohl natürlich in einer eher billiger Weg.
InformationsquelleAutor der Antwort Jon Skeet
"als" wird NULL zurückgeben, falls nicht möglich, zu werfen.
casting vor wird eine Ausnahme ausgelöst.
Für die Leistung, das auslösen einer exception ist in der Regel teurer in der Zeit.
InformationsquelleAutor der Antwort Patrick Desjardins
Hier ist eine weitere Antwort, mit einigen IL-Vergleich. Betrachten Sie die Klasse:
Schauen Sie sich jetzt den IL jede Methode produziert. Auch wenn die op-codes bedeuten nichts für Sie, können Sie sehen, mit einem großen Unterschied - isinst genannt wird, gefolgt von castclass in der DirectCast Methode. So zwei Aufrufe statt einem im Grunde.
Der isinst Schlüsselwort gegen die castclass
In diesem blog-post hat einen angemessenen Vergleich zwischen den beiden Möglichkeiten, es zu tun. Seine Zusammenfassung ist:
Ich persönlich benutze immer So, denn es ist leicht zu Lesen und empfohlen von der .NET-Entwicklungs-team (oder Jeffrey Richter sowieso)
InformationsquelleAutor der Antwort Chris S
Einer der subtilen Unterschiede zwischen den beiden ist, dass die "as" - keyword nicht verwendet werden kann für das casting, wenn ein cast-operator beteiligt ist:
Diese wird nicht kompiliert (obwohl ich denke, es hat in früheren Versionen) auf der letzten Zeile, da das "als" Schlagworte nicht nehmen cast-Operatoren berücksichtigt werden. Die Linie
string cast = (string)f;
funktioniert genauso gut, obwohl.InformationsquelleAutor der Antwort Patrik Hägne
als nie eine Ausnahme auslöst, wenn es nicht die Konvertierung der Rückkehr null statt (als arbeitet auf Referenz-Arten). Also mit als ist im Grunde gleichwertig zum
C-style-casts, auf der anderen Seite, werfen eine Ausnahme, wenn keine Konvertierung möglich ist.
InformationsquelleAutor der Antwort Anton Gogolev
Nicht wirklich eine Antwort auf deine Frage, aber ich denke, dass ist ein wichtiger Punkt im Zusammenhang.
Wenn Sie die Programmierung einer Schnittstelle, die Sie sollten nicht brauchen, zu werfen. Hoffentlich werden diese casts sind sehr selten. Wenn nicht, müssen Sie wahrscheinlich zu überdenken einige Ihrer Schnittstellen.
InformationsquelleAutor der Antwort toad
Bitte ignorieren Jon Skeet Beratung, re:vermeiden Sie das testen-und-cast-Muster, dh.:
Die Idee, dass dies mehr kostet, als eine Besetzung und einen null-test ist ein MYTHOS:
Es ist eine Mikro-Optimierung, das funktioniert nicht. Ich lief einige echte tests, und testen-und-cast ist tatsächlich schneller als cast-und-null-Vergleich, und es ist sicherer, auch, weil Sie nicht über die Möglichkeit mit einem null-Verweis in den Bereich außerhalb der wenn sollte der cast fehl.
Wenn Sie möchten, einen Grund, warum die test-und die Umwandlung ist schneller oder zumindest nicht langsamer, gibt es eine einfache und komplexe Grund.
Einfach: auch naiv-Compiler verschmelzen zwei ähnliche Operationen, wie zum Beispiel test-und-Darsteller, in einem einzigen test und Verzweigung. cast-und-null-test zwingen können, zwei tests und ein Zweig, eine für die Typprüfung und-Konvertierung auf null Fehler, eine für die null-check selbst. Zumindest, werden Sie beide zu optimieren, um einen einzelnen test und Verzweigung, so dass test-and-cast wäre weder langsamer noch schneller als cast-und-null-test.
Komplex: warum test-und cast ist schneller: cast-und-null-test stellt eine weitere variable in den äußeren Umfang, das muss der compiler track für ausführen, um liveness, und es kann nicht in der Lage zu optimieren der Weg, die variable, je nachdem wie Komplex dein control-flow ist. Umgekehrt, test-und-cast stellt eine neue variable, die nur in einem begrenzten Umfang, so weiß der compiler, dass die variable dead nach dem Umfang beendet, und so optimieren können, registrieren Zuordnung besser.
Also bitte, BITTE lass dieses "cast-und-null-test ist besser als der test-and-cast" Beratung STERBEN. BITTE. test-und-cast ist sowohl sicherer und schneller.
InformationsquelleAutor der Antwort naasking
Wenn der cast fehlschlägt, die 'wie' - Schlüsselwort nicht eine Ausnahme: es setzt die variable auf null (oder auf seinen Standardwert für value-Typen) statt.
InformationsquelleAutor der Antwort TheSmurf
Dies ist nicht eine Antwort auf die Frage, aber Kommentar auf die Frage code-Beispiel:
In der Regel sollten Sie nicht über zu werfen Sie ein Objekt aus, z.B. IMyInterface zu MyClass. Die große Sache über Schnittstellen ist, dass wenn man ein Objekt als Eingabe, die eine Schnittstelle implementiert, als Sie nicht zu kümmern, welche Art von Objekt Sie bekommen.
Wenn Sie die Umwandlung IMyInterface, MyClass, als Sie schon davon ausgehen, dass Sie erhalten ein Objekt vom Typ MyClass und es macht keinen Sinn, IMyInterface, weil, wenn Sie füttern Sie Ihren code mit anderen Klassen, die IMyInterface implementieren, es würde brechen, dein code...
Nun, mein Rat: wenn Ihre Oberflächen sind gut gestaltet, Sie können vermeiden, eine Menge von typecasting.
InformationsquelleAutor der Antwort f3lix
Den
as
Betreiber ist nur für Referenz-Typen, es kann nicht überlastet werden, und es wird zurücknull
wenn die operation fehlschlägt. Es wird nie eine exception werfen.Casting kann verwendet werden auf jedem kompatiblen Typen, kann es überlastet werden, und es wird eine exception werfen, wenn die operation fehlschlägt.
Die Wahl, welche zu verwenden, hängt von den Umständen ab. In Erster Linie ist es eine Frage, ob Sie werfen eine Ausnahme, die auf eine fehlgeschlagene Konvertierung.
InformationsquelleAutor der Antwort Jeffrey L Whitledge
Meine Antwort ist nur eine Frage der Geschwindigkeit in den Fällen, wenn wir nicht überprüfen Sie den Typ und wir überprüfen Sie nicht null-Werte nach dem Gießen. Ich fügte zwei zusätzliche tests, um Jon Skeet code:
Ergebnis:
Versuchen Sie nicht, den Fokus auf die Geschwindigkeit haben (wie ich), da ist dies alles sehr sehr schnell.
InformationsquelleAutor der Antwort CoperNick
Neben all dem, was war bereits ausgesetzt hier, ich kam gerade über einen praktischen Unterschied ist denke ich erwähnenswert, zwischen expliziten casting
Vergleich mit der
as
Betreiber.Hier ist das Beispiel:
Bottom line: GenericCaster2 wird nicht arbeiten mit struct-Typen. GenericCaster wird.
InformationsquelleAutor der Antwort Veverke
Wenn Sie die Office-PIAs-targeting .NET Framework 4.X verwenden Sie die als Schlüsselwort, da es sonst nicht kompiliert.
Casting ist OK, wenn die Ausrichtung .NET 2.0 allerdings:
Beim anvisieren .NET 4.X die Fehler sind:
Fehler CS0656: Fehlende compiler erforderlich Mitglied " Microsoft.CSharp.RuntimeBinder.Binder.Convert"
Fehler CS0656: Fehlende compiler erforderlich Mitglied " Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo.Erstellen Sie"
InformationsquelleAutor der Antwort Olivier MATROT
Den
as
Schlüsselwort funktioniert genauso wie eine explizite Umwandlung zwischen kompatiblen Verweis-Typen mit dem großen Unterschied, dass es nicht die eine Ausnahme auslösen, wenn die Konvertierung fehlschlägt. Vielmehr ergibt einen null-Wert in der Zielvariable. Da Ausnahmen sind sehr teuer in Bezug auf Leistung, es gilt als eine viel bessere Methode des Gießens.InformationsquelleAutor der Antwort Cerebrus
Was Sie wählen, hängt stark von, was erforderlich ist.
Ich bevorzuge die explizite Umwandlung
weil, wenn das Objekt sollte von der IMyInterface Typ und es ist nicht - es ist definitiv ein problem.
Es ist besser, Fehler so früh wie möglich, da die genauen Fehler behoben werden, anstatt die Festsetzung der Nebenwirkung.
Aber, wenn Sie sich mit Methoden, die akzeptiert
object
als parameter, dann müssen Sie prüfen Ihre genauen Typ vor ausführen von code. In einem solchen Fallas
würde nützlich sein, so können Sie vermeidenInvalidCastException
.InformationsquelleAutor der Antwort Oleg
Kommt drauf an, willst du auf null prüfen, nachdem mit "als" oder würden Sie es vorziehen, Ihre app eine exception werfen?
Meine Faustregel ist, wenn ich immer damit rechnen, dass die variable auf den Typ " ich gehe davon aus, dass ich zu der Zeit will ich nutzen, eine Besetzung. Wenn es möglich ist, dass die variable nicht umgewandelt, was ich will und ich bin bereit, um null-Werte von mit als ich als.
InformationsquelleAutor der Antwort Darryl Braaten
Haben Sie einen Blick auf diese links:
zeigen Sie Ihnen einige details und performance-tests.
InformationsquelleAutor der Antwort juFo
Die OP ist das problem beschränkt auf eine bestimmte casting-situation. Der Titel deckt viel mehr Situationen.
Hier ein überblick über alle relevanten casting-Situationen, die ich momentan denken kann:
InformationsquelleAutor der Antwort Tobias Knauss