2012-04-30 24 views
16

Ich muss ein heterogenes List von Objekten erstellen (benutzerdefinierte Klassen). Mein erster Gedanke war, eine List<ISomeMarkerInterface> zu erstellen, aber ich habe schnell gelernt, dass dies nicht das ist, was ich will. Mein nächster Gedanke war List<dynamic> und das schien keine schlechte Idee zu sein. Allerdings habe ich einige Nachforschungen angestellt und bin auf diese article about boxing and unboxing gestoßen und im Beispiel machen sie im Grunde, was ich will mit List<Object>.Liste <Object> vs Liste <dynamic>

Abgesehen von der Tatsache, dass dynamic zur Laufzeit und zum Zeitpunkt der Kompilierung Object ausgewertet werden, was ist der Unterschied zwischen List<dynamic> und List<Object>? Sind sie nicht im Wesentlichen dasselbe?

+2

Warum müssen Sie heterogene Objekte in derselben Liste speichern? Nur neugierig ... –

+0

sollten Sie für dynamische vs Objekt suchen, überprüfen Sie diesen Thread, antwortet er wahrscheinlich Ihre Antwort http://StackOverflow.com/Questions/3442821/Dynamic-VS-Objekt-Typ – Habib

+0

Ich habe eine Klasse, wo man der Eigenschaften ist eine Sammlung von Elementen, die für diese Klasse relevant sind und nicht denselben Typ haben, aber als Gruppe relevant sind. – Jason

Antwort

19

Es gibt 3 "allgemeine" Typen (obwohl nicht alle echte Typen sind) in C#: object, var und dynamic.

Objekt

Eine tatsächliche Art, wie jede andere Art, mit einer Sonderregel: Wenn ein Typ erbt nicht, erbt es von Objekt. Daraus folgt, dass alle Typen erben von Objekt, direkt oder indirekt.

Hervorhebung: Objekt ist ein Typ. Ein Objekt kann vom Typ Objekt sein, und der Typ hat seine Methoden wie ToString(). Da alles von Objekt erbt, kann alles in Objekt umgewandelt werden. Wenn Sie ein Objekt in ein Referenzobjekt zuordnen, tun Sie Upcasting wie wenn Sie auf eine Tier Referenz einen Elephant Typen Objekt zuweisen, wo Elephant von Tiere erbt.

SomeType x = new SomeType(); 
object obj = x; 
obj.DoSomething(); 
  • obj wird als Typ Objekt behandelt bei der Kompilierung und wird vom Typ Objekt zur Laufzeit (was logisch ist, da es sich um eine tatsächliche Typ ist - obj wird als Objekt deklariert kann
  • obj.DoSomething() dieser Art), so dass nur sein einen Fehler bei der Kompilierung verursachen wird, als ob Ject hat diese Methode nicht, unabhängig davon, ob SomeType es hat.

Var

Dies ist kein echter Typ, es ist lediglich eine Abkürzung für „Compiler, für mich die Art herauszufinden, basierend auf der rechten Seite der Zuweisung“.

SomeType x = new SomeType(); 
var obj = x; 
obj.DoSomething(); 
  • obj wird als Typ Sometype bei der Kompilierung behandelt und wird vom Typ Sometype zur Laufzeit, da nur, wenn Sie „Sometype“ geschrieben hatte, anstelle von „var“ .
  • wenn Sometype eine Methode hat DoSomething(), wird dieser Code funktioniert
  • wenn Sometype nicht das Verfahren haben, bewirkt, dass der Code einen Fehler bei der Kompilierung

Dynamisch

Dies ist ein Typ, der den Compiler anweist, die Überprüfung der Kompilierzeit für die Variable zu deaktivieren. Ein Objekt wird mit dem Typ dynamisch zur Kompilierzeit und Laufzeit behandelt.

SomeType x = new SomeType(); 
dynamic obj = x; 
obj.DoSomething(); 
  • obj ist vom Typ dynamischen bei der Kompilierung und Laufzeit
  • wenn Sometype ein Verfahren DoSomething hat(), wird dieser Code
  • wenn Sometype Doesn arbeiten‘ t haben die Methode, der Code wird kompilieren, aber eine Ausnahme zur Laufzeit
  • nicht auslösen e, dass dynamische Ausnahmen sehr leicht nachlässig, wenn verwendet verursachen können:

    public void f(dynamic x) 
    { 
        x.DoSomething(); 
    } 
    

Diese eine Ausnahme ausgelöst wird, wenn x von einem Typ ist, der nicht die DoSomething Methode hat, aber es Es ist weiterhin möglich, es aufzurufen und jedes Objekt als Parameter ohne einen Kompilierungsfehler zu übergeben, was einen Fehler verursacht, der nur zur Laufzeit und möglicherweise nur unter bestimmten Umständen angezeigt wird - ein potentieller Fehler. Wenn Sie also dynamic in einer beliebigen öffentlichen Schnittstelle einer Klasse verwenden, sollten Sie immer manuell zur Laufzeit durch Reflektion prüfen, sorgfältig mit Ausnahmen umgehen oder es gar nicht erst machen.

Hinweis: Das Objekt, auf das verwiesen wird, ändert seinen Typ natürlich nie. Während Obj kann Objekt sein, die x, dass es sich bezieht, ist immer noch SomeType.

+4

- 1 für sagen, dass "dynamische" ist kein tatsächlicher Typ (sehr unterschiedlich von 'var' was _istnicht_ ein tatsächlicher Typ, wie Sie richtig sagen). 'dynamic' ist definitiv ein Typ in C#, es ist sogar ein _static_ Typ, aber ein Objekt vom Typ' dynamic' umgeht die statische Typprüfung. Weitere Informationen finden Sie in Abschnitt 4.7 der C# -Sprachspezifikation oder unter diesem Link (http://msdn.microsoft.com/en-us/library/dd264736.aspx). – Nailuj

+0

Ups, ich habe es behoben. Ich hätte zuerst nachsehen sollen. : D Ich dachte, dass dynamic wurde sofort in den entsprechenden Typ auf Zuweisung Laufzeit aufgelöst und wurde nie wirklich als "dynamisch" getippt, aber das ist offenbar nicht der Fall. – svinja

+1

Nicht mehr -1 :) – Nailuj

2

Der Unterschied ist, dass, wenn Sie Objekt verwenden und Sie versuchen, auf einige Mitglieder Ihres Objekts zugreifen, wird es eine Kompilierzeit Fehler sein (weil Objekt dieses Mitglied nicht hat). Um zu arbeiten, müssen Sie wissen, was der Typ ist und ihn werfen.

Mit dynamischen können Sie auf jedes Mitglied zugreifen - keine Kompilierzeit Fehler. Wenn das Mitglied zur Laufzeit nicht existiert, wäre dies ein Laufzeitfehler. Dies ist der Weg zu gehen, wenn Sie wissen, dass Ihre heutogene Objekte alle zum Beispiel das gleiche Mitglied haben.

Wenn dies jedoch der Fall ist, gibt es eine andere, klarere Lösung: Sie können eine Schnittstelle definieren, mit diesem Mitglied und dann alle Ihre hetogeneous Objekte implementieren und Ihre Liste kann List<IYourInterface> sein.

Denken Sie daran, dass die dynamische Leistung aufgrund der guten, dynamischen Auflösung etwas schlechter sein kann.

+0

mit dynamischen, können Sie die Existenz eines Mitglieds überprüfen und weitermachen, wenn es nicht da ist, ohne einen Fehler zu werfen? Art von wie in Javascript, wie Sie etwas wie 'if (data.something) {}' tun können? – Jason

+1

Dies wird als Reflexion bezeichnet. Sie können es mit oder ohne * dynamic * verwenden. Schauen Sie in GetType(), GetMethod() usw. – svinja

+0

+1, wenn Sie die Reflektionsroute hinuntergehen, können Sie auch einfach Object verwenden (aber ich würde immer noch die Marker-Schnittstelle darüber empfehlen) – MattDavey