我有一個抽象類作為各種實作的基類。
讓它看起來像這樣:
public abstract class MyBase {
public object Property1 { get; protected set; }
}
重要的Property1是 isobject和 not的型別object?。我希望完全清楚Property1在實作實體中永遠不會為空。
假設一個典型的實作如下所示:
public sealed class MyImpl : MyBase {
public MyImpl() {
Property1 = new object();
}
}
當然,在現實世界中,基類中有很多屬性,它們的型別多種多樣,而不僅僅是object. 我可以將屬性標記為abstract,但是我必須在每個實作類中實作它們——這意味著更多的樣板代碼沒有真正的好處,對吧?
好的,但現在我收到一個警告,在退出建構式之前屬性必須具有非空值 - CS8618。當然我可以禁用我的基類的警告,但是有沒有更優雅的方法來指示編譯器實作類必須將這些屬性設定為非空值而不是禁用警告?
如果我收到的警告不是針對基類,而是針對實作(如果它沒有設定這些屬性之一),那將是完美的。
正如我已經發現的那樣 - 最新的 C# 編譯器和 Visual Studio 有很多神奇的特殊屬性可以改變可以為空的警告行為,但我不知道去哪里找。
uj5u.com熱心網友回復:
重要的是,Property1 的型別是 object 而不是 object?。我希望完全清楚 Property1 在實作實體中永遠不會為空。
保證這一點的唯一protected方法是使用建構式,MyBase其中需要為屬性賦值或Property1 創建屬性。Property1abstract
在 .NET 中,當子類被實體化時,首先它的超型別的建構式運行完成,然后是下一個子型別的建構式,以此類推。目前.NET 中沒有規定超型別具有在最派生型別的建構式運行之后運行的“后建構式”(我希望有..),因此MyBase類無法證明Property1構造物件時將處于有效狀態的編譯器。擁有 aprotected set不是任何可證明的保證(至少就編譯器而言):它相當于一個子類的 OOP,它說“我發誓要在我的建構式中設定這個屬性!” 你的程式的其余部分必須相信??這個口頭承諾。
這就是為什么自 C# 8.0 以來可以為空的注解如此重要和如此有用的原因:因為現在我們不再需要僅僅依靠信任進行操作:我們現在可以讓編譯器實際驗證欄位/自動屬性是否實際分配給非-null 值,從而防止任何NullReferenceException(每個人都喜歡的例外!)首先被拋出。
在這種情況下,非子abstract類sealed對編譯器無關緊要,因為您MyBase仍然可以通過從不設定的行為不端的子類單獨派生Property1。
當然,在現實世界中,基類中有很多屬性,它們的型別多種多樣,而不僅僅是
object. 我可以將屬性標記為abstract,但是我必須在每個實作類中實作它們——這意味著更多的樣板代碼沒有真正的好處,對吧?
我很欣賞必須復制 粘貼或手動擊鍵重復成員很煩人,但如果(重新)實作這些abstract成員在您的業務/域模型中表達一些有意義的東西,那么這樣做并不是“樣板”。
我收到警告,在退出建構式之前屬性必須具有非空值 - CS8618。當然我可以禁用我的基類的警告,但是有沒有更優雅的方法來指示編譯器實作類必須將這些屬性設定為非空值而不是禁用警告?
只需使用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 )
{
}
}
uj5u.com熱心網友回復:
您可能正在使用 net 6。只需從專案屬性中注釋或洗掉可為空的選項。您將擺脫許多問題和警告
<!--<Nullable>enable</Nullable>-->
有些人認為它很有用,但我懷疑,因為您可以開始手動將專案中所有類的所有屬性設定為空。
所以另類
public object? Property1 { get; protected set; }
這甚至看起來非常荒謬,因為默認情況下,參考型別在所有其他語言中都是可以為空的。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/428605.html
