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.]

6 Comments

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

  • 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)

  • 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.

  • 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)

    {

    }

    }

  • 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);

    }

    }

  • 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'".

Comments have been disabled for this content.