私はちょうど奇妙なことに遭遇しました、そして私は少し気になっています=現時点で吹き飛ばされています...
次のプログラムは正常にコンパイルされますが、実行するRuntimeBinderException
と、を読み込もうとするとが表示されますValue
。'object' does not contain a definition for 'Value'
class Program
{
interface IContainer
{
int Value { get; }
}
class Factory
{
class Empty : IContainer
{
public int Value
{
get { return 0; }
}
}
static IContainer nullObj = new Empty();
public IContainer GetContainer()
{
return nullObj;
}
}
static void Main(string[] args)
{
dynamic factory = new Factory();
dynamic container = factory.GetContainer();
var num0 = container.Value; // WTF!? RuntimeBinderException, really?
}
}
これが心を打つ部分です。次のように、ネストされた型をクラスFactory+Empty
の外に移動します。Factory
class Empty : IContainer
{
public int Value
{
get { return 0; }
}
}
class Factory...
そして、プログラムは問題なく実行されます、誰もがそれがなぜであるかを説明するのを気にしますか?
編集
コーディングの冒険では、もちろん、最初に考えるべきことをしました。そのため、私がクラスprivateとinternalの違いについて少しとりとめのないように見えます。これはInternalsVisibleToAttribute
、最初からほのめかしているものの、テストプロジェクト(この場合はビットを消費していた)を設計どおりに動作させるように設定したためです。
残りの良い説明については、EricLippertの回答を読んでください。
私が本当に警戒したのは、動的バインダーがインスタンスのタイプの可視性を念頭に置いていることでした。私はJavaScriptの経験が豊富で、パブリックやプライベートのようなものが実際にはないJavaScriptプログラマーとして、可視性が重要であるという事実に完全にだまされました。つまり、私はこのメンバーにアクセスしているかのようにアクセスしていました。これはパブリックインターフェイスタイプでしたが(動的は単にリフレクションの構文糖衣だと思いました)、動的バインダーは、単純なキャストを使用してヒントを与えない限り、そのような仮定を行うことはできません。