gpt4 book ai didi

C#如何标记抽象类的属性不为空,因为在实现类构造函数时需要设置(CS8618)?

转载 作者:行者123 更新时间:2023-12-02 18:18:38 25 4
gpt4 key购买 nike

我有一个抽象类作为各种实现的基类。

让它看起来像这样:

public abstract class MyBase {

public object Property1 { get; protected set; }

}

重要的是,Property1 的类型是object 而不是object?。我希望完全清楚 Property1 在实现实例中永远不会为 null。

假设典型的实现如下所示:

public sealed class MyImpl : MyBase {

public MyImpl() {
Property1 = new object();
}

}

当然,在现实世界中,基类中有很多属性,而且它们的类型各不相同,而不仅仅是object。我可以将这些属性标记为 abstract,但是我必须在每个实现类中实现它们 - 这意味着更多的样板代码并没有真正的好处,对吧?

好的,但现在我收到一条警告,在退出构造函数之前属性必须具有非空值 - CS8618。当然,我可以为我的基类禁用警告,但是是否有更优雅的方法来指示编译器实现类必须将这些属性设置为非空值而不是禁用警告?

如果我收到的警告不是针对基类的,而是针对未设置这些属性之一的实现的警告,那将是完美的。

正如我已经发现的那样 - 最新的 C# 编译器和 Visual Studio 有很多神奇的特殊属性可以改变可为 null 的警告行为,但我不知道去哪里找。

最佳答案

It is important, that the type of Property1 is object and not object?. I want it to be completely clear that the Property1 is never null in implementation instance.

保证这一点的唯一方法是使用MyBase 中的protected 构造函数,它需要Property1 的值通过使Property1成为抽象属性。

在 .NET 中,当子类被实例化时,首先它的父类(super class)型的构造函数运行完成,然后是下一个子类型的构造函数,依此类推。目前在 .NET 中没有规定父类(super class)型有一个在最派生类型的构造函数运行之后运行的“后构造函数”(我希望有……),所以 MyBase 没有办法 类以向编译器证明 Property1 在构造对象时将处于有效状态。拥有一个 protected set 不是任何一种可证明的保证(至少就编译器而言):它是 OOP 等同于子类说“我小指发誓要在我的 build 者!”并且程序的其余部分必须相信这个口头 promise 。

这就是自 C# 8.0 以来的可空注释如此重要和有用的原因:因为现在我们不再需要仅仅基于信任来操作:我们现在可以让编译器实际验证一个字段/auto-property 实际上被分配给一个非空值,从而防止任何 NullReferenceException(每个人最喜欢的异常类型!)从一开始就被抛出。

在这种情况下,非抽象子类是密封这一事实对编译器来说无关紧要,因为您的MyBase仍然可以派生分别由一个从不设置 Property1 的行为不当的子类。

Of course in real world there are plenty of properties in the base class and they are of various types, not just object. I could mark the properties as abstract, but then I would have to implement them in each implementing class - that would mean more boilerplate code with no real benefit in that, right?

我明白必须复制+粘贴或手动击键输入重复的成员很烦人,但如果(重新)实现那些抽象成员在你的代码中表达了一些有意义的东西,那么这样做不是“样板”业务/领域模型。

I get a warning that the properties must have non-null values before exiting constructor - CS8618. Of course I can disable the warning for my base class, but is there a more elegant way to instruct the compiler that the implementing class MUST set those properties to non-null values instead of disabling the warning?

只需使用一个protected 构造函数。这正是他们的目的。

像这样:

public abstract class MyBase
{
protected MyBase(object property1Value)
{
this.Property1 = property1Value ?? throw new ArgumentNullException(nameof(property1Value));
}

public object Property1 { get; }

}

这样所有的子类都是安全的:

public sealed class Derived : MyBase
{
public Derived()
: base( GetProperty1FromAStaticFactory() )
{

}
}

public sealed class Derived : MyBase
{
public Derived( Object p1Value )
: base( p1Value )
{

}
}

关于C#如何标记抽象类的属性不为空,因为在实现类构造函数时需要设置(CS8618)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71188860/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com