1

私が持っているとしましょうList<IMyInterface>...

、、、を実装する 3 つのクラスがありますIMyInterfaceMyClass1MyClass2MyClass3

私は読み取り専用の辞書を持っています:

private static readonly Dictionary<Type, Type> DeclarationTypes = new Dictionary<Type, Type>
{
    { typeof(MyClass1), typeof(FunnyClass1) },
    { typeof(MyClass2), typeof(FunnyClass2) },
    { typeof(MyClass3), typeof(FunnyClass3) },
};

私は別のインターフェースを持っています、IFunnyInteface<T> where T : IMyInterface

私は方法を持っています:

public static IFunnyInterface<T> ConvertToFunnyClass<T>(this T node) where T : IMyInterface
{
    if (DeclarationTypes.ContainsKey(node.GetType())) {
        IFunnyInterface<T> otherClassInstance = (FunnyInterface<T>) Activator.CreateInstance(DeclarationTypes[node.GetType()], node);
        return otherClassInstance;
    }
    return null;
}

FunnyClasses のコンストラクターを呼び出して、パラメーターとして MyClass オブジェクトを挿入しようとしています。それがどのオブジェクトかは知りたくありません。 MyClass をパラメーターとして使用して FunnyClass をインスタンス化したいだけです。

ConvertToFunnyClass を呼び出すとどうなるかT、タイプは IMyInterfaceであり、それを にキャストしようとすると、たとえば にFunnyInterface<T>変換できないと表示されますFunnyClass1FunnyInterface<IMyInterface>

私の現在の回避策(美しいものではありません)は次のとおりです。

public static dynamic ConvertToFunnyClass<T>(this T node) where T : IMyInterface
{
    if (DeclarationTypes.ContainsKey(node.GetType())) {
        var otherClassInstance = (FunnyInterface<T>) Activator.CreateInstance(DeclarationTypes[node.GetType()], node);
        return otherClassInstance;
    }
    return null;
}

そして、戻り値の型がdynamicであるため、私はそれが好きではありません。そのため、別の場所からアクセスすると、それがどの型であるかがわかりません。インテリセンスなどが失われます。パフォーマンスへの影響についてもわかりません。

手がかりはありますか?

前もって感謝します!

解像度

私は C# 4.0 を使用しているので、共分散 (出力位置のみ) を使用してエラーのキャストを停止できたのでIFunnyInterface

IFunnyInteface<out T> where T : IMyInterface

返信ありがとうございます。

4

2 に答える 2

1

基本的に、問題はに変換しようとしていることFunnyInterface<T>ですFunnyInterface<IMyInterface>。何度か言及されているように(1つの例はここにあり、詳細はここにあります)、これはほとんどの状況で有効ではありません。.NET 4でのみ、ジェネリック型がインターフェイスまたはデリゲートであり、型パラメーターがinまたはoutでバリアントとして明示的に宣言されている場合、この変換を実行できます。

FunnyInterface実際にはインターフェースですか?

于 2011-07-22T16:04:47.163 に答える
1

thecoop answer は、それができない理由を正確に示しています。

問題に対するよりクリーンな解決策 (動的を使用する以外) は、ベースの非ジェネリック インターフェイスです。

public interface IFunnyInterfaceBase
{
}

public interface IFunnyInteface<T> : IFunnyInterfaceBase 
    where T : IMyInterface
{
}

また、そのコードで使用するメソッド シグネチャを IFunnyInterface から IFunnyInterfaceBase に移動する必要があります。

このようにして、次のように書くことができます。

MyClass2 c2 = new MyClass2();
IFunnyInterfaceBase funnyInstance = c2.ConvertToFunnyClass();

コードで取得したと述べた例外は、拡張メソッドの署名自体によるものではありません (メソッドは問題ありません)。左辺値の型 (戻り値を格納するために使用する変数の型) が原因です!

明らかに、この解決策は、IFunnyInterface ソース コードを変更できる場合にのみ適用されます。

于 2011-07-22T16:31:06.743 に答える