【问题标题】:Chaining Constructors in .NET.NET 中的链式构造函数
【发布时间】:2017-01-03 03:20:50
【问题描述】:

我尝试通过尽可能重用构造函数来节省代码并降低可维护性的故障率。现在,我遇到了一种情况,我认为我必须复制代码,但也许你知道一个解决方案。

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
  }
}

每个以 XMLNode 作为参数的构造函数在初始化之前都会调用无参数构造函数。但是如何管理,派生类Foo调用自己的无参构造函数和带有基类XmlNode参数的构造函数呢?

构造函数链的期望行为是:

Foo(XmlNode)->Bar(XmlNode)->Foo()->Bar()

【问题讨论】:

  • 您希望期望的行为是什么?我不清楚
  • 只需调用 一个 构造函数来构造对象 ... 就足够了。如果需要,我认为base(node) 应该已经致电base()。
  • 是 Foo 类和 Bar 类的区别只有 List 和 List (希望不是)。如果是这样,为什么不只上一节课Foo&lt;T&gt;{ List&lt;T&gt; FooList}
  • 在这个问题上有很多微妙的变化。选择最佳答案将取决于您在 Bar(XmlNode) 构造函数中执行的操作。
  • Each constructor with XMLNode as parameter calls the parameterless constructor before for initialisation - 我没有看到 Foo(XmlNode node) 调用 this()。这种事情不是通常用内部私有(或受保护的).Init() 方法处理,所有构造函数都可以使用吗?

标签: c# .net oop inheritance constructor


【解决方案1】:

为什么不抽象构造函数的工作? 类似于:[检查新函数初始化]

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
    }
}

【讨论】:

    【解决方案2】:

    如果我正确理解您的问题,您希望Foo(XmlNode node) 致电this() 和base(node),这是无法完成的。

    顺便说一句:ctor() : base() 或在你的情况下 Foo() : base() 是隐含的。

    您唯一的选择是代码冗余。

    例如:

    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>();
        }
    }
    

    【讨论】:

      【解决方案3】:

      正如其他人已经回答的那样,除非您将行为抽象到单独的方法中,否则您想要做的事情是不可能的。

      但是,如果您想坚持使用构造函数,另一种方法是使用可选参数,如下所示:

      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 
          }
        }
      }
      

      当然,这里的折衷方案是你现在在构造函数中有分支逻辑。

      【讨论】:

        【解决方案4】:

        这就是为什么我总是以相反的方式链接构造函数的原因(无参数调用带有一个参数的ctor,它调用带有两个参数的ctor,等等)。每个构造函数的目的只是为缺少的参数提供一个默认值,并且它的主体保持为空。然后所有的工作都将在最专门的构造函数中完成,它调用基类的最专门的构造函数。这样一来,您始终只有一个需要维护的实现。

        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
            }
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2023-03-05
          • 2013-03-25
          相关资源
          最近更新 更多