Base Constructor Calls With Out Parameters

I’ve thought about this for a while, but I can’t figure out the answer. Maybe someone can help me with this.
One note before we start, I’d like to ask everyone to not comment about whether the design looks good or not, but on the specific language features that I find lacking.


Take the class MyBaseClass which is as follows:

public class MyBaseClass
{
public MyBaseClass(out int myParameter)
{
// Do initialization on myParameter.
// Do magic…

}
}
This class takes one parameter to its instance constructor, which is an out parameter.
Instace creation may look like this:
int i;
MyBaseClass myInstance = new MyBaseClass(out i);
Everything’s peachy, Right?


Now take the class MyDerivedClass which derives from MyBaseClass:

public class MyDerivedClass : MyBaseClass
{
private int m_MyInteger;
public MyDerivedClass() : base(out m_MyInteger)
{
// Do magic…
}
}
Oh, but wait. There’s a compiler error in there! You can’t pass an instance member to the call to the base constructor, even though it makes complete sense!
What you can pass is a type (static) member.


Now, my question is this: Why can’t I pass an instance member as an out parameter to a call to a base constructor?

[Update: My original meaning was not why it was not allowed to send an instance member to the base constructor (I do understand that), but why it is not allowed to send an instance member specifically with an out modifier to the base constructor. There is no need for the value to be set into that member yet. Also, Ron Buckton has a good workaround for this, if anyone requires it.]

Advertisements

7 thoughts on “Base Constructor Calls With Out Parameters

  1. Simple answer is your second class isnt initialized yet so you cant use one of those members.

  2. It is not a problem of out.

    "An instance constructor initializer cannot access the instance being created. Therefore it is a compile-time error to reference this in an argument expression of the constructor initializer, as it is a compile-time error for an argument expression to reference any instance member through a ‘simple-name’." (17.10.1, C# Language Specification)

  3. All private members would be created BEFORE class constructor is called. However I think still there is reason to not allow this at compiler level. Before the base class constructor code is being executed, all private variables of derived class would have been allocated memory space but their initializers (for example int i = DateTime.Now.Seconds) might not have ran yet. So if you pass a private member of a derived class to base class as out parameter, after the base class constructor is finished, their initializers would start running and wipe out any value assigned by base class constructor. This could result in difficult to find bugs and so is stopped by compiler even if you declare it as Out parameter. So now lets say you fix this by making explicit in specs that derived class member initializers would ran before the base constructor and allow out parameters. Still someone out there might think it’s not desirable because one could get confuse about who wins: private initilizers or base class constructor.

  4. dt,

    They don’t need to be initialized. They just have to have a reference ‘pointer’ allocated.

    Adrian,

    I have actually looked into the spec before posting this. The problem _is_ with out, since there’s no sense in using out or ref, since there will not be a value in the member.

    Sytelus,

    There’s no question about it – internal constructor code will always run after the call to the base/this constructor reference. This means that once you make a call with an out parameter, the member is instanciated.
    You can look about it in another way, that the setting of that specific member is done in the base constructor and you’re just passing it back. You won’t have to set it in your constructor (and it’s clear, since the call is not implicit), but you can.

  5. Here’s a workaround:

    class Foo
    {
    public Foo(out int x)
    {
    x = GetHashCode();
    }
    }

    class Bar : Foo
    {
    public Bar() : this(0)
    {
    }

    private Bar(int x) : base(out x)
    {
    }
    }

  6. re my previous comment: the x value is usable in the private constructor, e.g.

    class Foo
    {
    public Foo(out int x)
    {
    x = GetHashCode();
    }
    }

    class Bar : Foo
    {
    public Bar() : this(0)
    {
    }

    private Bar(int x) : base(out x)
    {
    Console.WriteLine(x);
    }
    }

  7. Omer,

    A constructor initializer can access the parameters of the constructor (like in Ron’s example – this is why it works) but cannot access the instance being created.

    base(out m_MyInteger) tries to access through m_MyInteger the INSTANCE of MyDerivedClass.

    Exactely the same error is thrown in the case WITHOUT out: "An object reference is required for the nonstatic field, method, or property ‘MyDerivedClass.m_MyInteger’".

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s