我如何确保调用所有这些构造函数?
How do I make sure all these constructors are called?
这是关于 c# 构造函数的,之前已被问过几次。但是,问题和答案从来都不适合我的情况:
public abstract class BaseClass {
public List<int> MyIntegers { get; set; }
public BaseClass()
{
this.MyIntegers = new List<int>();
}
public BaseClass(int initialInteger) : this()
{
this.MyIntegers.Add(initialInteger);
}
}
public class DerivedClass : BaseClass
{
public List<string> MyStrings { get; set; }
public DerivedClass()
{
this.MyStrings = new List<string>(); // does never get initialized
}
public DerivedClass(int initialInteger) : base(initialInteger)
{
this.MyStrings.Add(initialInteger.ToString()); <-- exception because DerivedClass() is never called
}
}
// In Program.cs (or where ever)
var derivedClass = new DerivedClass(10);
上面的代码将失败,因为 DerivedClass
的无参数构造函数从未被调用。所以,List<string> MyStrings
没有初始化。
我知道我不能同时使用 base() 和 this() 进行构造函数链接。但我当然可以这样做:
// Workaround
public DerivedClass(int initialInteger) : base(initialInteger)
{
this.MyStrings = new List<string>(); // redundant
this.MyStrings.Add(initialInteger.ToString());
}
这可行,但它非常难看,因为我使用了冗余代码。在简单的示例中似乎没问题,但在我的实际应用程序中,我将不得不添加大量冗余代码。不好看
你会如何优雅地解决这个问题?
根据经验,一个参数很少的构造函数应该委托给一个参数较多的构造函数,理想情况下只有一个构造函数来完成所有实际的初始化。
public abstract class BaseClass {
public List<int> MyIntegers { get; set; }
public BaseClass() : this(new List<int>()) { }
public BaseClass(int initialInteger) : this(new List<int>(){initialInteger}) { }
protected BaseClass(List<int> myIntegers) => MyIntegers = myIntegers;
}
public class DerivedClass : BaseClass
{
public List<string> MyStrings { get; set; }
public DerivedClass () : this(new List<string>(), new List<int>()) { }
public DerivedClass (int initialInteger) : this(new List<string>(){initialInteger},new List<int>(){initialInteger}) { }
protected DerivedClass (List<string> myStrings, List<int> myIntegers) : base(myIntegers) => MyStrings = myStrings;
}
这样做的缺点是某些 initialization-logic 是重复的,即派生的 class 需要创建一个整数列表以提供给 base-class。如果您的创建逻辑过于复杂,它可能暗示您的模型有问题,或者您应该将一些创建逻辑提取到单独的工厂 class。另一个可能有用的工具是反转控制容器。
这假设给定的问题是其他问题的占位符,因为这个特定的问题可以很容易地通过 params int[] initialValues
解决,正如 Damien_The_Unbeliever 在评论中建议的那样。
这是关于 c# 构造函数的,之前已被问过几次。但是,问题和答案从来都不适合我的情况:
public abstract class BaseClass {
public List<int> MyIntegers { get; set; }
public BaseClass()
{
this.MyIntegers = new List<int>();
}
public BaseClass(int initialInteger) : this()
{
this.MyIntegers.Add(initialInteger);
}
}
public class DerivedClass : BaseClass
{
public List<string> MyStrings { get; set; }
public DerivedClass()
{
this.MyStrings = new List<string>(); // does never get initialized
}
public DerivedClass(int initialInteger) : base(initialInteger)
{
this.MyStrings.Add(initialInteger.ToString()); <-- exception because DerivedClass() is never called
}
}
// In Program.cs (or where ever)
var derivedClass = new DerivedClass(10);
上面的代码将失败,因为 DerivedClass
的无参数构造函数从未被调用。所以,List<string> MyStrings
没有初始化。
我知道我不能同时使用 base() 和 this() 进行构造函数链接。但我当然可以这样做:
// Workaround
public DerivedClass(int initialInteger) : base(initialInteger)
{
this.MyStrings = new List<string>(); // redundant
this.MyStrings.Add(initialInteger.ToString());
}
这可行,但它非常难看,因为我使用了冗余代码。在简单的示例中似乎没问题,但在我的实际应用程序中,我将不得不添加大量冗余代码。不好看
你会如何优雅地解决这个问题?
根据经验,一个参数很少的构造函数应该委托给一个参数较多的构造函数,理想情况下只有一个构造函数来完成所有实际的初始化。
public abstract class BaseClass {
public List<int> MyIntegers { get; set; }
public BaseClass() : this(new List<int>()) { }
public BaseClass(int initialInteger) : this(new List<int>(){initialInteger}) { }
protected BaseClass(List<int> myIntegers) => MyIntegers = myIntegers;
}
public class DerivedClass : BaseClass
{
public List<string> MyStrings { get; set; }
public DerivedClass () : this(new List<string>(), new List<int>()) { }
public DerivedClass (int initialInteger) : this(new List<string>(){initialInteger},new List<int>(){initialInteger}) { }
protected DerivedClass (List<string> myStrings, List<int> myIntegers) : base(myIntegers) => MyStrings = myStrings;
}
这样做的缺点是某些 initialization-logic 是重复的,即派生的 class 需要创建一个整数列表以提供给 base-class。如果您的创建逻辑过于复杂,它可能暗示您的模型有问题,或者您应该将一些创建逻辑提取到单独的工厂 class。另一个可能有用的工具是反转控制容器。
这假设给定的问题是其他问题的占位符,因为这个特定的问题可以很容易地通过 params int[] initialValues
解决,正如 Damien_The_Unbeliever 在评论中建议的那样。