在下面的代碼中,單步除錯除錯器,觀察到MyWrapperInstance的一個實體Child.Wrapper,只有隱藏欄位來自Base.BaseWrapper填充為Child.Node通過new()型別約束中的建構式實體化的實體,因此MyWrapperInstance.Node仍然計算為null。
我對 C# 有點陌生,但這違背了我的直覺。有沒有解釋為什么會這樣?
var MyChildInstance = new Child();
var MyWrapperInstance = MyChildInstance.New();
// evaluates to true:
var isNull = MyWrapperInstance.Node is null;
public class Base
{
public class BaseNode { }
public class BaseWrapper
{
public BaseNode Node;
}
public TWrapper MakeNew<TWrapper, TNode>()
where TWrapper : BaseWrapper, new()
where TNode : BaseNode, new()
{
var wrapper = new TWrapper()
{
Node = null
};
// I expected this to write the derived class's property
// but it seems to write the hidden field of base class
// instead
wrapper.Node = new TNode();
return wrapper;
}
}
public class Child : Base
{
public class Node : BaseNode { }
public class Wrapper : BaseWrapper
{
// Hides BaseWrapper Property
public new Node Node;
}
public Wrapper New() => MakeNew<Wrapper, Node>();
}
注意:我使用 .NET 6.0 在 Visual Studio 17.3 中創建了一個新的控制臺應用程式,這是 Program.cs 的內容。
期望:MyWrapperInstance.Node 不為空,而隱藏屬性為空。我試圖在除錯器中檢查實體化wrapper沒有以某種方式轉換為BaseWrapper.
uj5u.com熱心網友回復:
正確的直覺 - 每當使用陰影(如public new Node Node;)時,最好假設訪問此類屬性,編譯器將隨機選擇基本版本或派生版本。確實,有明確定義的規則,并且在每種情況下都可以推斷編譯器將做出的選擇,但“隨機”是一個很好的起點。
在這種情況下,編譯器將TWrapper其視為至少BaseWrapper但對任何派生類一無所知的型別。因此,在泛型代碼內部wrapper.Node將始終是BaseWrapper.Node編譯器必須在編譯時生成所有代碼,并且它沒有關于本質上無關的資訊Wrapper.Node。
請注意,在大多數情況下,嘗試使用new修飾符virtual可能更合適 - 查看C# 中陰影和覆寫之間的區別?.
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/527060.html
標籤:C#哎呀阴影
上一篇:我應該使用基頁類還是創建輔助類?
