.net 引导初始化
我有两个类,一个继承自另一个。基类是MustInherit/abstract,并定义MustOverride/abstract属性 作为基类初始化的一部分,它根据抽象属性的值设置一个变量。问题是继承类接受应该分配给重写属性的值作为其参数。继承的类设置此属性,但不是在调用基类的初始值设定项之前 基本上,我需要初始化基类的一部分,然后允许继承类初始化它的一些属性,然后返回基类以完成初始化更多属性 我会使属性成为基类的一部分,但是继承类使用强类型,而基类只需要一个接口 代码示例:.net 引导初始化,.net,vb.net,.net,Vb.net,我有两个类,一个继承自另一个。基类是MustInherit/abstract,并定义MustOverride/abstract属性 作为基类初始化的一部分,它根据抽象属性的值设置一个变量。问题是继承类接受应该分配给重写属性的值作为其参数。继承的类设置此属性,但不是在调用基类的初始值设定项之前 基本上,我需要初始化基类的一部分,然后允许继承类初始化它的一些属性,然后返回基类以完成初始化更多属性 我会使属性成为基类的一部分,但是继承类使用强类型,而基类只需要一个接口 代码示例: MustInheri
MustInherit Class A
MustOverride Property X As IExample
Sub New()
' Do some stuff
_privateY = X.Foo() ' NullReferenceException
End Sub
End Class
Class B
Inherits A
Override Property X As IExample ' returns StrongX
Property StrongX As ConcreteExample ' ConcreteExample implements IExample
Sub New(x As ConcreteExample)
MyBase.New(x)
StrongX = x
End Sub
End Class
您可以使用一个
惰性:
公共抽象类A
{
private Lazy_privateY=new Lazy(()=>this.X.Foo());
}
您可以使用一个懒惰的:
公共抽象类A
{
private Lazy_privateY=new Lazy(()=>this.X.Foo());
}
正是由于这个原因,不应该在构造函数中调用抽象成员
如果您可以控制抽象类,我建议通过基类构造函数传入该值
public abstract class A
{
public A(IExample x)
{
// Do Stuff
var _privateY = x.Foo();
}
}
public class B : A
{
public B(IExample x):base(x) {}
}
正是由于这个原因,不应该在构造函数中调用抽象成员
如果您可以控制抽象类,我建议通过基类构造函数传入该值
public abstract class A
{
public A(IExample x)
{
// Do Stuff
var _privateY = x.Foo();
}
}
public class B : A
{
public B(IExample x):base(x) {}
}
编辑:对不起,我的答案是C#:(
一种选择是让基本抽象类调用子类可以实现的虚拟(或抽象)初始化方法:
public abstract class A
{
public abstract IExample X { get; set; }
private object _privateY;
protected A()
{
PreInit();
PostInit();
}
protected abstract void PreInit();
protected virtual void PostInit()
{
if (X == null)
throw new InvalidOperationException("Must assign a value to X.");
_privateY = X.Foo();
}
}
然后在B
中,覆盖PreInit
并分配数据:
public class B : A
{
public override IExample X { get; set; }
public B()
{
}
protected override void PreInit()
{
X = new ConcreteExample();
}
}
编辑:对不起,我的答案是C#:(
一种选择是让基本抽象类调用子类可以实现的虚拟(或抽象)初始化方法:
public abstract class A
{
public abstract IExample X { get; set; }
private object _privateY;
protected A()
{
PreInit();
PostInit();
}
protected abstract void PreInit();
protected virtual void PostInit()
{
if (X == null)
throw new InvalidOperationException("Must assign a value to X.");
_privateY = X.Foo();
}
}
然后在B
中,覆盖PreInit
并分配数据:
public class B : A
{
public override IExample X { get; set; }
public B()
{
}
protected override void PreInit()
{
X = new ConcreteExample();
}
}
(标记为C#和VB.NET,因为它与这两种语言都相关,但如果有建议,我希望有更多相关的标记。)仅仅因为C#和VB.NET都是面向对象的,并不意味着这个问题符合C#问题。这个问题与C#无关!!!尽管我在这个项目中使用了这两种语言,但我意识到这个问题在VB.NET或C#下都不完全合适。然而,OOP实现细节是针对.NET语言家族的。(标记为C#和VB.NET,因为它与这两种语言都相关,但如果有建议,我希望有更多相关的标记。)仅仅因为C#和VB.NET都是面向对象的,并不意味着这个问题符合C#问题。这个问题与C#无关!!!虽然我在这个项目中使用了这两种语言,但我意识到这个问题在VB.NET或C#下都不完全合适。然而,OOP实现细节是针对.NET语言家族的。Could甚至有public B():base(new ConcreteExample())
,正如Eric Lippert所说,“从构造函数调用虚拟方法是一种糟糕的编程实践。从构造函数调用虚拟方法是一个坏主意,因为派生类上的方法可能在派生类构造函数运行之前运行。”Kevin的解决方案是优雅的,并且有正确的想法。感谢文档。构造函数参数方法对我来说是可行的,但我不是一个大粉丝,因为它会让参数的数量感觉过多,并且可能会给人一种错误的印象,即基类正在以某种方式设置属性(或者应该设置)但是,它看起来是唯一的选择。它一点也不坏@Cyborgx37,这是一种很好的依赖注入方法。类a
实际上要求它有一个IExample
的实现,因此将它作为构造函数每次都满足了这一需要,并使创建子类的任何开发人员都能立即识别它(虽然您可能想考虑一个空校验,也许是一个代码>调试。断言< /代码>)。基类设置属性也是可以的。也许你可以将属性设置为public get;private set;
并放弃抽象
?谢谢@Chris。有时你会被某个特定的实现所包围,以至于需要其他人指出显而易见的东西。我想我会放弃抽象-这是r根本没有令人信服的理由。甚至可以像Eric Lippert所说的那样有public B():base(new ConcreteExample())
,“从构造函数调用虚拟方法是一种不好的编程实践。从构造函数调用虚拟方法是一种不好的做法,因为派生类上的方法可能在派生类构造函数运行之前运行。“Kevin的解决方案是优雅的,并且有正确的想法。感谢您提供的文档。构造函数参数方法对我来说很常见,但我不是一个很喜欢的方法,因为它会让参数的数量感觉过多,并且可能会给人一种错误的印象,即基类正在以某种方式设置属性(或者应该设置)但是,它看起来是唯一的选择。它一点也不坏@Cyborgx37,这是一种很好的依赖注入方法。类a
实际上要求它有一个IExample
的实现,因此将它作为构造函数每次都满足了这一需要,并使创建子类的任何开发人员都能立即识别它(虽然您可能想考虑一个空校验,也许是一个代码>调试。断言< /代码>)。基类设置属性也是可以的。也许你可以将属性设置为public get;private set;
并放弃摘要
?谢谢@Chris。有时你会被某个特定的实现所包围,以至于需要其他人指出显而易见的地方。我想我会放弃摘要