4

次のコードが実行時に例外をスローすることがわかったとき、私は驚きました。

class A
{
    public string Name { get; set; }

    public A()
    {
        Name = "Class A";
    }
}

class B
{
    public string Name { get; set; }

    public B()
    {
        Name = "Class B";
    }

    public static explicit operator A(B source)
    {
        return new A() {Name = source.Name};
    }
}


class Program
{
    static void Main(string[] args)
    {
        // This executes with no error
        var bInstance = new B();
        Console.WriteLine(bInstance.GetType()); // <assemblyname>.B
        var aInstance = (A) bInstance;
        Console.WriteLine(aInstance.Name); // Class B

        // This fails with InvalidCastException
        var bInstanceReflection = Activator.CreateInstance(typeof (B));
        Console.WriteLine(bInstanceReflection.GetType()); // <assemblyname>.B
        var aInstanceReflection = (A) bInstanceReflection;

        Console.WriteLine(aInstanceReflection.Name);
    }
}

誰か教えてもらえますか?何が起こったのかよくわかりません

4

3 に答える 3

7

驚かないでください-カスタム演算子は何もオーバーライドせず、オーバーロードします-したがって、実行時ではなくコンパイル時に選択されます。

コードから暗黙的な入力を削除すると、少し明確になります。

object bInstanceReflection = Activator.CreateInstance(typeof (B));
Console.WriteLine(bInstanceReflection.GetType()); // <assemblyname>.B
A aInstanceReflection = (A) bInstanceReflection;

これで、最終行で、が通常の参照変換を実行(A)するキャストにすぎないことはかなり明らかです。objectユーザー定義の変換はまったく適用されません。

.NET 4を使用している場合は、動的型付けを使用して機能させることができます。

// Note the change of type
dynamic bInstanceReflection = Activator.CreateInstance(typeof (B));
Console.WriteLine(bInstanceReflection.GetType()); // <assemblyname>.B
A aInstanceReflection = (A) bInstanceReflection;

現在、変換は動的な値に適用されています。つまり、使用する変換の選択は実行時まで延期されます。実行時は、カスタム演算子を使用します。

于 2011-08-02T12:19:57.700 に答える
3

を作成しましたB。そして、それをにキャストしAます。

レイアウトは似ていますが、BはAとは関係がありません。静的演算子はコンパイラによって適用されますが、実行時にキャストを介して適用されることはありません。C#の構文は同じですが、リフレクションを処理する場合は大きく異なります。

これは通常の予想される動作です。

于 2011-08-02T12:19:09.650 に答える
1

次の行を変更するだけです。

var bInstanceReflection = Activator.CreateInstance(typeof (B));

に:

var bInstanceReflection = (B)Activator.CreateInstance(typeof (B));

したがって、コンパイラはbInstanceReflectionのタイプを認識し、正しい暗黙の演算子を呼び出すことができます。

于 2011-09-09T15:00:11.180 に答える