1

JavaコードをC#に変換しようとしていますが、ジェネリックキャストに関して問題が発生しています。

私は次のメソッドを公開するCopyableと呼ばれるインターフェースタイプを持っています...

interface Copyable { void copyTo(Copyable target); }

そして、Copyableインターフェースを実装するために制限されているジェネリック型をパラメーターとして受け取るAtomicObject型...

class AtomicObject<T> where T : class, Copyable {
    public T openRead();

AtomicObjectsをオブジェクトタイプのディクショナリに格納しますが、AtomicObjectクラスに固有の「openRead」メソッドを呼び出すためにオブジェクトをAtomicObjectsにキャストバックする必要があります...

foreach (KeyValuePair<object, object> entry in dict)
{
    AtomicObject<Copyable> obj = (AtomicObject<Copyable>)entry.Key;
    Copyable dest = (Copyable)obj.openRead();//get the destination
}

AtomicObjectのパラメーターの役割を果たすListNodeタイプを実装しました...

class ListNode<T> : Copyable
AtomicObject<ListNode<string>> atomic = new AtomicObject<ListNode<string>>();

このコードをコンパイルすることはできますが、このプログラムを実行すると、ランタイムシステムがタイプのオブジェクトを変換できないため、「InvalidCastException」が生成されます。

AtomicObject<ListNode<string>> 

に...

AtomicObject<Copyable>. 

ただし、ListNodeのタイプはCopyableです。これが正しくキャストできない理由を誰かが説明できますか?最も重要なことは、ListNodeに含まれるパラメーターのタイプを知る必要があるDictionaryまたはforeachループに依存しない修正を誰かが提案できるかどうかです。たとえば、Javaでは...

AtomicObject<?> obj = (AtomicObject<?>)entry.Key;

ただし、これはC-Sharpでは不可能です。

4

2 に答える 2

3

共分散が必要であり、クラスを共変にすることはできないため、これを行うことはできません。

したがって、あなたからインターフェースを抽出する必要がありますAtomicObject

interface IAtomicObject<out T> where T : class, Copyable
{
    public T openRead();
}

out(ジェネリック宣言に注意してください)、AtomicObjectクラスに実装させてください。

その後、次のコードを実行できるはずです

foreach (KeyValuePair<object, object> entry in dict)
{
    IAtomicObject<Copyable> obj = (IAtomicObject<Copyable>)entry.Key;
    Copyable dest = obj.openRead();
}

また、.net 標準では、インターフェイス名の前に I を付けることが推奨されていることに注意してください。

于 2012-07-30T14:01:52.717 に答える
0

あなたが直面している問題は、ジェネリックが C# と Java でどのように実装されているかの違いによるものです。Java は、型消去を使用してジェネリックを実装します。つまり、実行時に anAtomicObject<Anything>が実質的に anになります。AtomicObject<Object>C# ではそうではありません。具体化された型を使用してジェネリックが実装されるため、実行時に型のパラメーター化が維持されます。C# では、 anAtomicObject<Whatever>は常に でありAtomicObject<Whatever>、決して ではありませんAtomicObject<SomethingElse>(AtomicObject がインターフェイスでない限り - 一般的な差異を参照してください)。

できることは、ループを含むメソッドを型パラメーター化することです。

(注 - C# のインターフェイスは、慣例により大文字の I で始まる必要があります。そのため、Copyable の名前を変更しました)

以下は、あなたが求めていることを行うべきだと思います。私はこのコードをテストしたことに注意してください:

public void DoSomething<TObj>(IEnumerable<AtomicObject<TObj>, Object> dict) 
    where TObj : ICopyable {
    foreach (KeyValuePair<AtomicObject<TObj>, Object> entry in dict)
    {
        ICopyable dest = entry.Key.openRead();
        // Whatever...
    }
}
于 2012-07-30T14:02:43.230 に答える