ICollection<T>.IsReadOnly
クラスからプロパティの明示的なインターフェイス実装をオーバーライドしようとしているときに、明示的なインターフェイス メンバーの実装は、またはCollection<T>
などの修飾子を持つことができないため、オーバーライドできないと述べているドキュメントに出くわしました。MSDNでは、明示的なインターフェイス メンバーの実装によって呼び出される別の抽象メンバーまたは仮想メンバーを作成することによって、明示的なインターフェイス メンバーの実装を継承できるようにする方法を指定するところまで行っています。これまでのところ問題はありません。virtual
abstract
しかし、私は疑問に思います: C# では、インターフェイスを明示的に指定するだけで、明示的に実装されたインターフェイス メンバーをオーバーライドできるのはなぜですか?
たとえば、プロパティとメソッドを使用して、次のような単純なインターフェイスがあるとします。
public interface IMyInterface
{
bool AlwaysFalse { get; }
bool IsTrue(bool value);
}
また、A
インターフェイスを明示的に実装しTest()
、独自のインターフェイス メンバー実装を呼び出すメソッドを持つクラス。
public class A : IMyInterface
{
bool IMyInterface.AlwaysFalse
{ get { return false; } }
bool IMyInterface.IsTrue(bool value)
{ return value; }
public bool Test()
{ return ((IMyInterface)this).AlwaysFalse; }
}
ご覧のとおり、4 つのメンバーはいずれも仮想または抽象ではないため、次のB
ようなクラスを定義すると、次のようになります。
public class B : A
{
public bool AlwaysFalse
{ get { return true; } }
public bool IsTrue(bool value)
{ return !value; }
}
B
次に、キャスト toのインスタンスが のA
ように動作することを期待しますA
。そしてそれは:
A a = new A();
Console.WriteLine(((IMyInterface)a).AlwaysFalse); // False
Console.WriteLine(((IMyInterface)a).IsTrue(false)); // False
Console.WriteLine(a.Test()); // False
A b = new B();
Console.WriteLine(((IMyInterface)b).AlwaysFalse); // False
Console.WriteLine(((IMyInterface)b).IsTrue(false)); // False
Console.WriteLine(b.Test()); // False
今、キャッチが来ます。クラス宣言の 1 つの点を除いてC
、完全なコピーであるクラスを作成します。B
public class C : A, IMyInterface
{ /* ... same as B ... */ }
のインスタンスがC
にキャストされると、 のA
ように動作するのではなく、 のように動作するようになりA
ましたC
。
A c = new C();
Console.WriteLine(((IMyInterface)c).AlwaysFalse); // True
Console.WriteLine(((IMyInterface)c).IsTrue(false)); // True
Console.WriteLine(c.Test()); // True
メソッドでさえ、Test()
オーバーライドされたメソッドをC
!で呼び出すようになりました。どうしてこれなの?