私は最近、ユニットテストのために基本クラスにインタフェースを導入し、奇妙な問題に遭遇しました。これは、最小限の再現性のあるシナリオです:インタフェースの継承とプロパティの隠蔽の問題
interface IBase
{
string Text { get; }
}
interface IChild : IBase
{
}
class Base : IBase
{
public string Text { get { return "Base"; }}
}
class Child : Base, IChild
{
public new string Text { get { return "Child"; }}
}
static void Main(string[] args)
{
var child = new Child();
Console.WriteLine(child.Text); // Outputs "Child"
Console.WriteLine((child as Base).Text); // Outputs "Base"
Console.WriteLine(((child as Base) as IBase).Text); // Outputs "Child"
}
最初の2つのConsole.WriteLine
コマンドの出力は論理的であるが、私は最後の1の出力を受け入れるに失敗タイプBase
の一時変数を使用した場合、それもChild
を出力します。誰でもここで何が起こっているのか説明できますか?
UPDATE
インタフェースIChild
を除去することにより、((child as Base) as IBase).Text
突然"Base"
もたらします。つまり、Child
がIBase
(直接またはインターフェイスの継承を使用)を実装している限り、結果は"Base"
の代わりに"Child"
になると私は結論づけています。
他のクラスのメソッドをリファクタリングしてIBase
の代わりにBase
の引数を取ると、これは突然異なる動作になります。 Base
に
(child as Base)
を、あなたはBase
のText
フィールドを使用している:
もちろん、この混乱を避ける必要があります。 '新メンバー 'を必要とすることは決して良いことではありません。 –
実際、その 'new'プロパティはデッドコードで例外を投げました。これは、コードが常に基本型を使用していたため使用されていませんでした。ベースインターフェイスを追加すると、死んだコードが生まれました:) –