2
class Base
{
}

class Derived1 : Base
{
}

class Derived2 : Base
{
    public static explicit operator Derived1(Derived2 d2)
    {
        return new Derived1();
    }
}

class Test
{
    static void Main()
    {
        Base bd2 = new Derived2();

        Derived1 d2ConvertedD1 = (Derived1)bd2; //throws InvalidCastException

    }
}

Unable to cast object of type 'ConsoleApplication1.Derived2' to type 'ConsoleApplication1.Derived1'.

なんで?演算子変換の何が問題になっていますか?

4

5 に答える 5

10

bd2問題は、のコンパイル時の型がBaseではなくであるため、カスタム変換が使用されていないことDerived2です。コンパイラはカスタム変換を考慮していないため、通常のキャストが含まれているだけです。これは明らかな理由で失敗しています。(その失敗を理解していると思います。そうでなければ、最初からカスタム変換を作成していなかったでしょう。)

演算子と変換は、オペランドのコンパイル時の型に基づいてコンパイラによって選択されます。

最初にキャストしたり、 の宣言を変更したりすることはできますが、私は個人的に方針を完全に変更し、全体像をもう一度見てみたいと思います。何をしようとしていますか、なぜですか? たとえば、仮想メソッドの方が理にかなっているでしょうか?Derived2bd2Base

于 2011-02-08T15:09:35.310 に答える
5

クラスを階層全体ではなく上下にのみキャストできます。

于 2011-02-08T15:07:52.667 に答える
1

オペレーターの署名を見てください。

public static explicit operator Derived1(Derived2 d2);

staticであることに注意してください。あなたが見ているのは、メソッドのオーバーロード解決の制限に似ています。

以下が「文字列」ではなく「オブジェクト」を出力するのと本質的に同じ理由です。

static void WriteObject(object obj) { Console.WriteLine("Object"); }
static void WriteObject(string str) { Console.WriteLine("String"); }

object obj = "I am a string.";
WriteObject(obj);

つまり、コンパイラはコンパイル時にオーバーロードを選択する必要があります。Basea から aへのキャストの場合Derived1、適切なシグネチャを持つオーバーロードがないため、実際のダウンキャストを試みます。bd2として宣言するとDerived2、他の人が述べたように、コンパイラがカスタム変換を選択できるようになるため、これが「修正」されます。

于 2011-02-08T15:15:13.570 に答える
0

クラス Derived2 はクラス Derived1 から継承していないため、これは失敗します。

以下が有効です。

ベース d2ConvertedBase = (ベース) bd2;

Derived2 が Derived1 を継承する場合、試したことは有効です。

于 2011-02-08T15:09:04.007 に答える
0

基本クラスにキャストします。複雑なクラス階層を作成している場合は、インターフェイスを実装し、インターフェイス ベースのプログラミングを行うことを検討してください。

于 2011-02-08T15:09:45.503 に答える