C# 在构造函数中不使用虚拟成员调用构造派生类属性
我有一些嵌套类,C# 在构造函数中不使用虚拟成员调用构造派生类属性,c#,oop,inheritance,design-patterns,C#,Oop,Inheritance,Design Patterns,我有一些嵌套类,BaseOuter和BaseInner,以及子类DerivedOuter和DerivedInnerBaseOuter具有属性BaseInner,当我实例化DerivedOuter时,我希望baseInner属性的运行时类型为DerivedInner 我首先像下面一样解决了这个问题,使用虚拟初始值设定项实例化baseInner,它在derivedouther中被重写。这允许我执行baseInner=newbaseinner()vsbaseInner=new-DerivedInner
BaseOuter
和BaseInner
,以及子类DerivedOuter
和DerivedInner
BaseOuter
具有属性BaseInner代码>,当我实例化DerivedOuter
时,我希望baseInner
属性的运行时类型为DerivedInner
我首先像下面一样解决了这个问题,使用虚拟初始值设定项实例化baseInner
,它在derivedouther
中被重写。这允许我执行baseInner=newbaseinner()代码>vsbaseInner=new-DerivedInner()在相应的初始值设定项中编码>
在注意到a并做了a之后,我决定我应该改变它。。。但是怎么做呢
我想到了几件事。我可以在调用构造函数后调用初始值设定项,需要调用代码来执行var baseOuter=new baseOuter();baseOuter.Initialize()代码>。我也许可以用工厂,但我得考虑一下。最后,我想做的类嵌套中可能存在设计缺陷
值得指出的是,执行newbaseinner()
非常昂贵,我不想简单地创建它然后扔掉
using System;
public class Program
{
public static void Main()
{
Console.WriteLine("new BaseOuter");
var baseOuter = new BaseOuter();
Console.WriteLine("\nnew DerivedOuter");
var derivedOuter = new DerivedOuter();
}
class BaseOuter{
protected BaseInner baseInner;
public BaseOuter(){
Console.WriteLine("BaseOuter Constructor");
/* lots of stuff I want in derived class */
// This is an anti-pattern I want to avoid
//https://www.jetbrains.com/help/resharper/2018.2/VirtualMemberCallInConstructor.html
InitializeInner();
}
protected virtual void InitializeInner(){
Console.WriteLine(" BaseOuter Initialize BaseInner");
baseInner = new BaseInner();
}
protected class BaseInner{
public int x;
public BaseInner(){
/* stuff that is needed in DerivedInner too */
Console.WriteLine(" BaseInner Constructor");
x = 2;
}
}
}
class DerivedOuter : BaseOuter {
public DerivedOuter() {
Console.WriteLine("DerivedOuter Constructor (finished)");
}
protected override void InitializeInner(){
Console.WriteLine(" DerivedOuter Initialize DerivedInner");
baseInner = new DerivedInner();
}
protected class DerivedInner : BaseInner {
public double y;
public DerivedInner(){
Console.WriteLine(" DerivedInner Constructor");
y = 2d;
}
}
}
}
输出
new BaseOuter
BaseOuter Constructor
BaseOuter Initialize BaseInner
BaseInner Constructor
new DerivedOuter
BaseOuter Constructor
DerivedOuter Initialize DerivedInner
BaseInner Constructor
DerivedInner Constructor
DerivedOuter Constructor (finished)
所有代码都可以在这里找到。这里有一种方法
它也在做同样的事情。不同之处在于派生类如何“重写”BaseInner的实现。它通过向构造函数提供一个实现来实现
internal class BaseOuter
{
protected BaseInner baseInner;
protected internal BaseOuter(BaseInner inner = null)
{
baseInner = inner ?? new BaseInner();
Console.WriteLine("BaseOuter Constructor");
/* lots of stuff I want in derived class */
// This is an anti-pattern I want to avoid
//https://www.jetbrains.com/help/resharper/2018.2/VirtualMemberCallInConstructor.html
}
protected internal class BaseInner
{
public int x;
public BaseInner()
{
/* stuff that is needed in DerivedInner too */
Console.WriteLine(" BaseInner Constructor");
x = 2;
}
}
}
internal class DerivedOuter : BaseOuter
{
protected internal DerivedOuter()
:base(new DerivedInner())
{
Console.WriteLine("DerivedOuter Constructor (finished)");
}
protected internal class DerivedInner : BaseInner
{
public double y;
public DerivedInner()
{
Console.WriteLine(" DerivedInner Constructor");
y = 2d;
}
}
}
如果您想进行全面的依赖项注入,可以从
protected internal BaseOuter(BaseInner inner = null)
这意味着BaseOuter
将与BaseInner
的任何实现完全解耦
其他一些建议:
- 除非有非常强烈的需求,否则我不会将类嵌套在彼此内部。它使用不多,所以乍一看可能会让人困惑
- 如果假定仅在调用构造函数时设置
baseInner
,请将其标记为readonly
。(ReSharper可能会这样建议。)
谢谢BaseOuter
构造函数将有一行baseInner=inner代码>也是,对吗?是的,我漏了一行。基类将使用派生类提供的实现(如果有)。但是如果没有一个实例(它为null),那么它将指定自己的实例。值得一提的是,如果我们需要创建许多内部实例,我们可以传入一个委托函数来实现这一点,例如(arg)=>new DerivedInner(arg)
。