tags:

views:

99

answers:

5

I am using a derived class and casting the base class to it using the as keyword. When I do this, the derived class constructor is being called, and it's objects initialized, but the derived instance does not end up with the initialized objects (has nulls). Here's a code sample.

// 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
    [...]
  }
}

Is the problem that "as" is normally used for derived->base and not base->derived or is there something else at work here?

+7  A: 

until jon skeet shows up to correctly answer this question, as far as i know the 'as' keyword is just a way of doing a cast that suppresses exceptions if the cast is invalid; it should not call any constructors on its own

so have you verified (e.g. in the debugger) that the passed-in object is properly initialized before the cast?

Steven A. Lowe
+1 You are correct, `as` only casts - no constructors are called.
Andrew Hare
What I have verified is that the constructor is hit. What I'm actually trying to solve is a case where a request comes in without all the body parameters specified whatsoever. This kills me, since I got to the object structure, where a null coming in means a null object, which will start to throw exceptions when members are accessed. I can do a catch of the nulls after I cast, but it seems like there should be a way to take care of it more gracefully.
TahoeWolverine
You should check to see that the JSON request deserializer is working properly. So at least throwing an exception for an incomplete request.
sixlettervariables
+3  A: 

As a point of clarification the as operator does not call any methods on the object in question. It merely finds out if the object can be converted to the type requested, and if so returns the instance as the type or null if it cannot (see the C# Language Specification Section 7.9.11 "The as operator").

From the code you have displayed, it appears that there is no reason for the CreateRequest to have the null properties unless the JSON request deserialization method explicitly sets them to null. You can show that this is the case by calling:

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

You will find both the as operator and the default constructor are working correctly.

sixlettervariables
+1 This is correct as well, as does not call user-defined conversions either. See http://msdn.microsoft.com/en-us/library/cscsdfbt(VS.71).aspx
Andrew Hare
Yeah 7.9.11 spells that out with: "Note that some conversions, such as user defined conversions, are not possible with the as operator and should instead be performed using cast expressions."
sixlettervariables
+1  A: 

The problem is that using 'as' doesn't call the constructor. It just casts the object to the new type (in this case, from Request to CreateRequest).

In your case, since Request doesn't have values for the fields...they are null after being cast.

Justin Niessner
If Request wasn't a CreateRequest the 'as'-cast would return null. The default constructor creates the properties with non-null values, so somewhere in the JSON deserialization the properties are made null.
sixlettervariables
We're talking C#...where did JSON come from?
Justin Niessner
His code says that (or rather implies) the Request object is made by a JSON request deserialization.
sixlettervariables
Looks like Steven beat me to it...but that's what I was trying to get at.
Justin Niessner
My breakpoints are getting hit in the constructor, but is it possible, perhaps, that the cast happens after that, thereby nullifying the variables anyay?
TahoeWolverine
The cast cannot cause the variables to become null. Either the cast will succeed because the object in question IS a CreateRequest, or the cast will fail because the object is some other Request.
sixlettervariables
A: 

Also, in addition to what stephan has said, (using 'as' cannot trigger a constructor),

... in yr question, you state

" I am using a derived class and casting the base class to it ..."

You cannot cast a base class to a derived class, only the other way around, so clearly either (hopefully) you are mis-stating yr question, or your assumptions are invalid in some way. Can you be more explicit?

Charles Bretana
You can *cast* a base class to a derived class, if and only if the derived class derives from the base class in question.
sixlettervariables
@sixletter... , you have it exactly backwards... You cannot cast an instance of a base class to the type of a derived class. ie. if you construct an instance of Animal, you cannot cast that instance to type Pig. otoh, if you have an instance of Pig, you can cast it to type Animal...
Charles Bretana
A: 

You can't use the "as" keyword to convert an instance of a base class to an instance of a derived class. If the object wasn't an instance of the derived class to begin with, the "as" keyword won't convert it into one.

Mark
Well, in this case it is, sort of. Dealing with JSON requests, the params coming in in the request match with the members of the class. My problem is that it seems that if someone makes a request, say without a body at all, then the objects within my request object start to throw exceptions when their members are accessed.
TahoeWolverine