如何在类层次结构中链接构造函数?

7
我们有以下类层次结构:
public class Base
{
    public Base()
    {
        // do generic initialization 
    }

    public Base(SomeClass param1) : this()
    {
        // init properties that require param1
    }

    public Base(SomeClass param1, OtherClass param2) : this(param1)
    {
        // init properties that require param2
    }

    // ...
}

public class Derived : Base
{
    public Derived()
    {
        // do custom initialization 
    }

    public Derived(SomeClass param1) : this() // ???
    {
        // do custom initialization using param1
    }

    public Derived(SomeClass param1, OtherClass param2) : this(param1) // ???
    {
        // do custom initialization using param2
    }

    // ...
}

我们需要Derived运行其自己的初始化程序和基类对应的初始化程序。我们如何在不重复代码/运行某些构造函数两次的情况下链接构造函数?
2个回答

5
在派生类链中,将具有最少参数的构造函数链接到具有最多参数的构造函数,然后将具有最多参数的派生构造函数链接到基类。就像这样:
public class Base 
{
  public Base() : this(null, null)
  {
  }
  public Base(SomeClass param1) : this(param1, null)
  {
  }
  public Base(SomeClass param1, OtherClass param2)
  {
    if (param1 != null)
    {
      // initialise param1
    }
    if (param2 != null)
    {
      // initialise param2
    }
  }
}

public class Derived : Base
{
  public Derived() : this(null, null)
  {
  }
  public Derived(SomeClass param1) : this(param1, null)
  {
  }
  public Derived(SomeClass param1, OtherClass param2) : base(param1, param2)
  {
  }
} 

根据上下文,使用default(T)来表示缺失/默认值可能比使用null更好。


@Mihai:为了用字符串来演示,可以看看我的答案。它证明了所有的构造函数都被调用了。 - user195488

3
一般来说,你需要将构造函数从最少的开始连接到最多的,像这样:

public Derived(SomeClass param1) : this(param1, param2)
{}

请查看C#中构造函数的文章以获取更多信息。
编辑:
根据下面的@Scott:
那么具有最多参数的将是public Derived(SomeClass param1, OtherClass param2) : base(param1, param2),您可以在Derivedbase的2个参数构造函数中放置初始化代码。
为了证明所有构造函数都被调用,我编写了一个程序:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication2
{
    public class Base
    {
        public Base()
            : this(null, null)
        {
        }
        public Base(string param1)
            : this(param1, null)
        {
        }
        public Base(string param1, string param2)
        {
            Console.WriteLine("Base Class: " + param1 + "+" + param2);

            if (param1 != null)
            {
                // initialise param1
            }
            if (param2 != null)
            {
                // initialise param2
            }
        }
    }

    public class Derived : Base
    {
        public Derived()
            : this("", "")
        {
        }
        public Derived(string param1)
            : this(param1, "")
        {
        }
        public Derived(string param1, string param2)
            : base(param1, param2)
        {
            Console.WriteLine("Derived Class: " + param1 + "+" + param2);
        }
    } 
    class Program
    {
        static void Main(string[] args)
        {
            Derived d = new Derived("test1", "test2");
            Console.ReadLine();
        }
    }
}

输出:

Base class: test1+test2
Derived class: test1+test2

2
如果调用它,您将将其设置为所需的默认值。例如,如果它们都是字符串,则为public Derived(string param1) : this(param1, "") - Scott Chamberlain
2
param2 是一个字面量、常量、静态字段或其他可用值。 - recursive
@siride:请查看此处最受赞同的答案以及它是如何实现的:https://dev59.com/kFnUa4cB1Zd3GeqPfO-U - user195488
1
正如Code Monkey所说,在派生类链中,将具有最少参数的构造函数链接到具有最多参数的构造函数,然后将具有最多参数的派生构造函数链接到基类。 - Polyfun
2
@siride:补充一下@Code Monkey的评论,具有最多参数的将是public Derived(SomeClass param1, OtherClass param2) : base(param1, param2),您可以在派生类和基类的两个参数构造函数中放置初始化代码。 - Scott Chamberlain
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接