1

I try to save code and reduce failure rate for maintainability by reusing constructors as much as possible. Now, I came across a Situation, where I think I'll have to duplicate code, but maybe you know a solution.

public class Bar {
  public List<string> BarList {
    get;
    private set;
  }

  public Bar() {
    this.BarList = new List<string>();
  }

  public Bar(XmlNode node)
    : this() {
    //create from xml
  }
}

public class Foo: Bar {
  public List<int> FooList {
    get;
    private set;
  }
  public Foo()
    : base() {
    this.FooList = new List<int>();
  }

  public Foo(XmlNode node)
    : base(node) {
    //create from enhanced xml
  }
}

Each constructor with XMLNode as parameter calls the parameterless constructor before for initialisation. But how to manage, that the derived class Foo calls its own parameterless constructor AND the the constructor with the XmlNode parameter of the base class?

The desired behaviour of constructor chain would be:

Foo(XmlNode)->Bar(XmlNode)->Foo()->Bar()
7
  • What would you like the desired behavior to be? It's not clear to me Commented Aug 26, 2016 at 12:37
  • It's sufficient to call just one constructor to have object ... constructed. I think base(node) should call base() already if it's required. Commented Aug 26, 2016 at 12:39
  • Is the difference between Foo class and Bar class is only List<int> and List<string> (I hope not). If so Why not just have one class Foo<T>{ List<T> FooList} Commented Aug 26, 2016 at 12:49
  • There are lots of subtle variations on this issue. Choosing the best answer would depend on what you are doing in the Bar(XmlNode) constructor. Commented Aug 26, 2016 at 12:50
  • Each constructor with XMLNode as parameter calls the parameterless constructor before for initialisation - I don't see Foo(XmlNode node) calling this(). Isn't this kind of thing usually handled with an internal private (or protected) .Init() method that can be used by all constructors? Commented Aug 26, 2016 at 12:52

4 Answers 4

2

Why you don't abstract the work of the constructor? Something like: [check new function init]

public class Foo : Bar
{
    public List<int> FooList
    {
        get;
        private set;
    }
    public Foo()
      : base()
    {
        Init();
    }

    private void Init() { this.FooList = new List<int>(); }

    public Foo(XmlNode node)
      : base(node)
    {
        Init();
        //create from enhanced xml
    }
}
Sign up to request clarification or add additional context in comments.

Comments

1

If I understand your question correctly you want Foo(XmlNode node) to call this() and base(node), which can't be done.

btw: ctor() : base() or in your case Foo() : base() is implicit.

Your only option here is a bit of code-redundancy.

E.g:

public class Foo: Bar {
    public List<int> FooList { get; private set; }

    public Foo() : base() {
        Initialize();
    }

    public Foo(XmlNode node) : base(node) {
        Initialize();
    }

    protected void Initialize() {
        this.FooList = new List<int>();
    }
}

Comments

1

As others have answered, what you're looking to do is not possible unless you abstract the behaviour out into a separate method.

An alternative, however, if you wanted to stick with constructors is to use optional parameters as follows:

public class Bar {
  public List<string> BarList {
    get;
    private set;
  }

  public Bar(string xmlNode = null) {
    this.BarList = new List<string>();

    if (xmlNode != null) { 
        //create from xml 
    }
  }
}

public class Foo: Bar {
  public List<int> FooList {
    get;
    private set;
  }
  public Foo(string xmlNode = null)
  : base(xmlNode)
  {
    this.FooList = new List<int>();

    if (xmlNode != null) { 
        //create from enhanced xml 
    }
  }
}

Of course, the compromise here is now you have branching logic in the constructors.

Comments

0

That's the reason, why I chain constructors always the other way around (the parameterless calls ctor with one parameter, which calls ctor with two parameters, etc). The purpose of each constructor is just to provide a default value for the missing parameter and its body stays empty. All the work will then be done in the most specialized constructor, which calls the most specialized constructor of the base class. That way you always have only one implementation that needs to be maintained.

public abstract class Bar
{
    public List<string> BarList { get; private set; }

    public Bar()
        : this(null)
    { }

    public Bar(XmlNode node)
    {
        this.BarList = new List<string>();

        if (node == null)
            return;

        //create from xml
    }
}

public class Foo : Bar
{
    public List<int> FooList { get; private set; }

    public Foo()
        : this(null)
    { }

    public Foo(XmlNode node)
        : base(node)
    {
        this.FooList = new List<int>();

        if (node == null)
            return;

        //create from enhanced xml
    }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.