1

假设我有一个List<IMyInterface>...

我有三个实现IMyInterface: MyClass1,MyClass2MyClass3

我有一个只读字典:

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是 type IMyInterface,当我尝试将它转换为 时FunnyInterface<T>,它说我无法转换FunnyClass1,例如FunnyInterface<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>. 正如已经多次提到的(一个例子在这里,更多信息在这里),这在大多数情况下是无效的。只有在 .NET 4 中,当泛型类型是接口或委托,并且类型参数已使用 or 显式声明为变体时inout才能执行此转换。

FunnyInterface实际上是一个接口吗?

于 2011-07-22T16:04:47.163 回答
1

thecoop 的回答准确地指出了为什么你不能这样做。

一个更清洁的问题解决方案(除了使用动态)将是一个基本的非泛型接口:

public interface IFunnyInterfaceBase
{
}

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

并且您需要将该代码中使用的方法签名从 IFunnyInteface 移动到 IFunnyInterfaceBase。

这样你就可以写出这样的东西:

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

你说你在你的代码中得到的异常不是由于扩展方法签名本身(方法很好)..它是由你的左值类型(你用来存储其返回值的变量的类型)引起的!

显然,此解决方案仅适用于您可以修改 IFunnyInterface 源代码!

于 2011-07-22T16:31:06.743 回答