3

C# では、環境によって次の型が提供されるシナリオにいます。

public interface IFoo {
}

public abstract class Base {
}

public class Derived : Base, IFoo {
}

public class Arbitrary {
    public Base GetBase() { }
}

これに加えて、私が書いたものは次のとおりです。Arbitrary.GetBase()私のコードでは、常にのインスタンスを返すことを保証できることに注意してくださいDerived

public class Arbitrary2 : Arbitrary {
    public IFoo GetDerived() {
        return (IFoo)base.GetBase();
    }
}

ただし、このコードは「タイプ 'Base' を 'IFoo' に変換できません」というメッセージで失敗します。

しかし、私がこれを行うと、うまくいきます:

public class Arbitrary2 : Arbitrary {
    public IFoo GetDerived() {
        Object baseAsObject = base.GetBase();
        return (IFoo)baseAsObject ;
    }
}

IFoo にダウンキャストする前に、この Object へのアップキャストが必要なのはなぜですか? 2 つのコードは機能的に同一であり、キャストが無効な場合、後者は実行時に確実にクラッシュします。コンパイラが不平を言う理由がわかりません。

4

6 に答える 6

6

これを行う必要はありません。あなたのコードはそのまま動作するはずです。詳細については、このプログラムを参照してください。

using System;

public interface IFoo { }

public abstract class Base { }

public class Derived : Base, IFoo { }

public class Arbitrary {
    public Base GetBase() { return new Derived(); }
}

public class Arbitrary2 : Arbitrary {
    public IFoo GetDerived() {
        return (IFoo)base.GetBase();
    }
}

class Program
{
    static void Main(string[] args)
    {
        Arbitrary2 test = new Arbitrary2();
        IFoo check = test.GetDerived();

        Console.WriteLine(check.GetType().Name);

        Console.WriteLine("Press key to exit:");
        Console.ReadKey();
    }
}
于 2012-07-11T18:25:24.437 に答える
1

書けないのか

public class Arbitrary2 : Arbitrary {
    public IFoo GetDerived() {
        return (Derived)this.GetBase();
    }
}

コンパイラは と の間の接続を確認するDerivedためBase、 への明示的なキャストはDerived問題ないはずです。その場合、 anyDerivedは確かにIFooであるため、追加の時間をキャストする必要はありません (その変換は暗黙的です)。

base.キーワードを使用しないでください。(上記のように)言うthis.か、除外します。

編集:また、元のコードコンパイルされましたが、私のバージョンは少し読みやすいかもしれません。

于 2012-07-11T21:08:22.180 に答える
1

GetBase() メソッドは Base を返しますが、これは IFoo を実装していません。

于 2012-07-11T18:25:26.927 に答える
1

BaseIFooとは関係がないため、に変換できませBaseIFoo:

public abstract class Base { }

この宣言に基づいてBase、タイプではないインスタンスが存在する可能性が非常に高くなりますIFooBase実際、この宣言に基づいて、コンパイラは の特定のインスタンスがを実装すると仮定する理由はまったくありませんIFoo

Derived実装IFoo:

public class Derived : Base, IFoo { }

しかし、あなたは を返しているのDerivedではなく、 を返していますBase。それをポリモーフィングすることでObject、コンパイラを効果的に「だます」ことになります。あなたは、あなたがそれよりも多くのことを知っているので、あなたの言うことを聞くべきだと伝えています. 実際にコンパイラよりも多くのことを知っている限り、これは問題ありません。そして、コンパイラが知らないことを知っているのは、 のすべてのインスタンスがBaseにポリモーフできるということIFooです。

その場合、単に実装IFooしないのはなぜBaseですか?そうすれば、あなたの知識をコンパイラと共有することができ、誰もが満足するでしょう.

于 2012-07-11T18:27:54.107 に答える
1

コンパイラが明示的なキャストを禁止する理由は、Base実装されていないためIFooです。

が常に a を返すことを保証できる場合は、キャストの前にキャスト to を挿入できます。GetBase()DerivedDerivedIFoo

public class Arbitrary2 : Arbitrary {
    public IFoo GetDerived() {
        return (IFoo)(Derived)base.GetBase();
    }
}

もちろん、間違っていると実行時にスローされます。または、失敗した場合にasのみ返されるキャストを使用できます。null

public class Arbitrary2 : Arbitrary {
    public IFoo GetDerived() {
        return base.GetBase() as IFoo;
    }
}
于 2012-07-11T18:28:09.233 に答える
1

Arbitrary.GetBase()のインスタンスを返しますBaseBaseの階層には含まれていませんIFoo.

実行時には、はい、オブジェクトはDerivedインスタンスですが、コンパイラが知っていること、つまりクラスの関係に基づいて、接続がないため、最初のメソッドで試しているようにキャストBaseする方法はありません。IFoo

于 2012-07-11T18:29:01.120 に答える