2009-08-17 6 views
1

Ich verwende eine abgeleitete Klasse und übergebe die Basisklasse mit dem Schlüsselwort as. Wenn ich dies tue, wird der abgeleitete Klassenkonstruktor aufgerufen, und seine Objekte werden initialisiert, aber die abgeleitete Instanz endet nicht mit den initialisierten Objekten (hat Nullen). Hier ist ein Codebeispiel.Objektinitialisierungen gehen durch Verwendung des Schlüsselwortes "as" verloren.

// classes 
public class Request 
{ 
    public Request(); 
    public Header Header{get;set;} 
} 

public class CreateRequest : Request 
{ 
    public Foo Foo{get;set;} 
    public Bar Bar{get;set;} 

    public CreateRequest():base() 
    { 
    this.Foo = new Foo(); 
    this.Bar = new Bar(); 
    } 
} 

public class SomeClass 
{ 
    private Response ProcessCreateRequest(Request request) 
    { 
    // request comes from a json request 
    CreateRequest createRequest = request as CreateRequest; 
    // values of Foo and Bar are null 
    [...] 
    } 
} 

Ist das Problem, dass „als“ normalerweise für derived-> Base verwendet wird und Base- nicht> abgeleitet oder ist es etwas anderes, bei der Arbeit hier?

Antwort

7

bis Jon Skeet auftaucht, um diese Frage richtig zu beantworten, so weit ich weiß, ist das 'as' Schlüsselwort nur eine Art, einen Cast zu machen, der Ausnahmen unterdrückt, wenn der Cast ungültig ist; Es sollte keine Konstruktoren für sich selbst aufrufen.

Haben Sie also verifiziert (z. B. im Debugger), dass das übergebene Objekt vor der Umwandlung ordnungsgemäß initialisiert wurde?

+0

+1 Sie sind richtig, 'as' nur wirft - keine Konstruktoren werden aufgerufen. –

+0

Was ich verifiziert habe, ist, dass der Konstruktor getroffen wird. Was ich eigentlich zu lösen versuche, ist ein Fall, in dem eine Anfrage ohne alle angegebenen Körperparameter eingeht. Das bringt mich um, da ich in die Objektstruktur geriet, wo ein hereinkommender Nullwert ein Null-Objekt bedeutet, das beim Zugriff auf Mitglieder mit dem Auslösen von Ausnahmen beginnt. Ich kann die Nullen fangen, nachdem ich gecastet habe, aber es scheint, als sollte es einen Weg geben, sich eleganter darum zu kümmern. – TahoeWolverine

+0

Sie sollten prüfen, ob der JSON-Deserialisierer ordnungsgemäß funktioniert.Also zumindest eine Ausnahme für eine unvollständige Anfrage werfen. – user7116

3

Zur Verdeutlichung ruft der Operator as keine Methoden für das betreffende Objekt auf. Es findet lediglich heraus, ob das Objekt in den angeforderten Typ konvertiert werden kann, und wenn dies der Fall ist, gibt es die Instanz als Typ oder null, wenn dies nicht möglich ist (siehe C# -Sprachspezifikation Abschnitt 7.9.11 "Der as-Operator").

Aus dem Code, den Sie angezeigt haben, scheint es keinen Grund für die CreateRequestnull Eigenschaften zu geben, es sei denn, die JSON-Anforderung Deserialisierungsmethode setzt sie explizit auf null. Sie können zeigen, dass dies der Fall ist durch den Aufruf:

var response = ProcessCreateRequest(new CreateRequest()); 
System.Diagnostics.Debug.Assert(response.Foo != null); 
System.Diagnostics.Debug.Assert(response.Bar != null); 

Sie finden sowohl die as Operator und die Standard-Konstruktor korrekt arbeiten.

+0

+1 Dies ist auch korrekt, da auch keine benutzerdefinierten Konvertierungen aufgerufen werden. Siehe http://msdn.microsoft.com/en-us/library/cscsdfbt(VS.71).aspx –

+0

Yeah 7.9.11 buchstabiert das mit: "Beachten Sie, dass einige Konvertierungen, wie benutzerdefinierte Konvertierungen, nicht möglich sind mit dem as-Operator und sollte stattdessen mit Cast-Ausdrücke durchgeführt werden. " – user7116

1

Das Problem ist, dass die Verwendung von "as" den Konstruktor nicht aufruft. Es wird nur das Objekt auf den neuen Typ (in diesem Fall von Request to CreateRequest) umgesetzt.

In Ihrem Fall, da Request keine Werte für die Felder hat ... sind sie nach dem Cast null.

+0

Wenn Request kein CreateRequest war, würde der 'as'-Cast null ergeben. Der Standardkonstruktor erstellt die Eigenschaften mit Nicht-Null-Werten. Daher werden die Eigenschaften in der JSON-Deserialisierung auf Null gesetzt. – user7116

+1

Wir reden C# ... woher kam JSON? –

+1

Sein Code besagt, dass das Request-Objekt durch eine JSON-Anfrage-Deserialisierung erzeugt wird (oder eher impliziert). – user7116

-1

Auch zusätzlich zu welchem ​​stephan gesagt hat, (unter Verwendung ‚als‘ nicht einen Konstruktor auslösen kann),

... in yr Frage, geben Sie

"Ich bin eine abgeleitete Klasse mit und die Basisklasse dazu umwandeln ... "

Sie können eine Basisklasse nicht in eine abgeleitete Klasse umwandeln, nur umgekehrt, so dass entweder (hoffentlich) Sie Ihre Frage falsch angeben oder Ihre Annahmen ungültig sind irgendwie. Kannst du expliziter sein?

+0

Sie können eine Basisklasse in eine abgeleitete Klasse umwandeln, wenn und nur wenn die abgeleitete Klasse von der betreffenden Basisklasse abgeleitet ist. – user7116

+0

@sixletter ..., Sie haben es genau rückwärts ... Sie können keine Instanz einer Basisklasse in den Typ einer abgeleiteten Klasse umwandeln. dh. Wenn Sie eine Instanz von Animal erstellen, können Sie diese Instanz nicht in den Typ Pig umwandeln. otoh, wenn du eine Instanz von Pig hast, kannst du sie auf Animal tippen ... –

0

Sie können das Schlüsselwort "as" nicht verwenden, um eine Instanz einer Basisklasse in eine Instanz einer abgeleiteten Klasse zu konvertieren. Wenn das Objekt zu Beginn keine Instanz der abgeleiteten Klasse war, wird das Schlüsselwort "as" es nicht in eins umwandeln.

+0

Nun, in diesem Fall ist es so. Beim Umgang mit JSON-Anfragen stimmen die in der Anfrage eingehenden Parameter mit den Mitgliedern der Klasse überein. Mein Problem ist, dass wenn jemand eine Anfrage macht, sagen wir ohne Körper, dann fangen die Objekte in meinem Anfrageobjekt an, Ausnahmen auszulösen, wenn auf ihre Mitglieder zugegriffen wird. – TahoeWolverine

Verwandte Themen