5

この質問を、考えられる最も単純なコード サンプルにまで絞り込みました。明示的な演算子がジェネリック メソッドから呼び出されないのはなぜですか?

class Program
{
    static void Main(string[] args)
    {
        A a = new A();
        B b = (B)a; // works as expected
        b = Cast<B>(a);
    }

    static TResult Cast<TResult>(object o)
    {
        return (TResult)o; // throws Invalid Cast Exception
    }
}

class A
{
}

class B
{
    public static explicit operator B(A a)
    {
        return new B();
    }
}
4

2 に答える 2

10

ジェネリック メソッドには、 に基づく1セットの ILがあるためTResultです。呼び出し元ごとに異なる IL は実行されません。また、ジェネリックには演算子TResult がありません。

また、ここでの演算子は と の間である必要がありobjectTResultを含む演算子を定義することはできませんobject

例: Cast<int>and Cast<string>and Cast<Guid>all はまったく同じ IL を持ちます。

あなたはでカンニングすることができますdynamic

return (TResult)(dynamic)o;
于 2013-01-09T20:53:04.203 に答える
2

つまり、implicitandexplicit演算子は真の変換演算子ではないということです。それらは完全にコンパイル時の構文糖衣です。コードがコンパイルされると、変換演算子については何も残りません。

コンパイラが見たとき:

B b = (B) new A();

A「 からへのネイティブな変換 (暗黙的または明示的) はありBますか?」(これは、たとえばAextendedの場合、またはto (implicit) またはto (explicit) などのいくつかの特殊なケースの言語変換のいずれかの場合です。)Bdoubleintintdouble

そうでない場合は、ユーザー定義の変換演算子を検索します (たとえば、 and の定義のみを検索し、Aからおよび への暗黙的な変換Bの の定義は検索しません)。見つかった場合は、その演算子を静的メソッド呼び出しとして挿入するため、コードは次のようになります。CAB

B b = B.SomeAutogneratedName(new A());

そうすれば、ランタイムに到達するまでに、ランタイムが実行方法を知っている別のメソッドを実行するだけです。許可されている実際の実行時変換演算子は、言語に組み込まれたほんの一握りです (つまり、任意の基本型から親型へ、および特定のプリミティブ型間で)。

于 2013-01-09T21:19:45.533 に答える