类型参数 - 从类型 T 获取具体类型:IMyInterface
假设我有一个 List
...
我有三个实现 IMyInterface
的类:MyClass1
、MyClass2
,和 MyClass3
我有一个只读字典:
private static readonly Dictionary<Type, Type> DeclarationTypes = new Dictionary<Type, Type>
{
{ typeof(MyClass1), typeof(FunnyClass1) },
{ typeof(MyClass2), typeof(FunnyClass2) },
{ typeof(MyClass3), typeof(FunnyClass3) },
};
我有另一个接口,IFunnyInteface
我有一个方法:
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;
}
我试图调用unnyClasses的构造函数并插入我的MyClass对象作为参数。我不想知道它是哪个对象:我只想用 MyClass 作为参数实例化一些FunnyClass。
当我调用 ConvertToFunnyClass 时会发生什么,T
的类型为 IMyInterface
,当我尝试将其转换为 FunnyInterface
时,它说我例如,无法将 FunnyClass1
转换为 FunnyInterface
我当前的解决方法(不是一个漂亮的方法)是这样的
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;
}
:不喜欢它,因为返回类型是动态的,所以当我从其他地方访问它时,我不知道它是什么类型,并且我失去了智能感知之类的东西。我也不知道对性能有何影响。
有什么线索吗?
提前致谢!
解决方案
由于我使用的是 C# 4.0,我可以使用协方差(仅输出位置)来停止转换错误,因此我将 IFunnyInterface
更改为
IFunnyInteface<out T> where T : IMyInterface
感谢大家的回复。
Suppose I have a List<IMyInterface>
...
I have three classes which implement IMyInterface
: MyClass1
, MyClass2
, and MyClass3
I have a readonly Dictionary:
private static readonly Dictionary<Type, Type> DeclarationTypes = new Dictionary<Type, Type>
{
{ typeof(MyClass1), typeof(FunnyClass1) },
{ typeof(MyClass2), typeof(FunnyClass2) },
{ typeof(MyClass3), typeof(FunnyClass3) },
};
I have another interface, IFunnyInteface<T> where T : IMyInterface
I have a method:
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;
}
I'm trying to call the constructor of FunnyClasses and insert as parameter my MyClass object. I don't want to know which object it is: I just want to instantiate some FunnyClass with MyClass as a parameter.
What happens when I call ConvertToFunnyClass, T
is of type IMyInterface
, and when I try to cast it to FunnyInterface<T>
, it says I can't convert FunnyClass1
, for instance, to FunnyInterface<IMyInterface>
My current workaround (not a beautiful one), is this:
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;
}
And I don't like it because the return type is dynamic
, so when I access it from somewhere else, I have no idea what type it is, and I lose intellisense, and stuff. I don't know about any performance implications either.
Any clues?
Thanks in Advance!
Resolution
As I'm using C# 4.0, I could stop casting errors using covariance (output positions only), and so I changed my IFunnyInterface
to
IFunnyInteface<out T> where T : IMyInterface
Thank you all for the replies.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
本质上,您的问题是您试图将
FunnyInterface
转换为FunnyInterface
。正如多次提到的(一个例子是 此处,更多信息此处),这在大多数情况下无效。仅在 .NET 4 中,当泛型类型为接口或委托,并且类型参数已使用in
或out
显式声明为变体时,才能执行此转换。FunnyInterface
实际上是一个接口吗?Essentially, your problem is that you are trying to convert
FunnyInterface<T>
toFunnyInterface<IMyInterface>
. As has been mentioned several times (one example is here, more information here), this is not valid in most circumstances. Only in .NET 4, when the generic type is an interface or delegate, and the type parameter has been explicitly declared as variant within
orout
, can you perform this conversion.Is
FunnyInterface
actually an interface?thecoop 的答案准确地向您指出了为什么您不能这样做。
解决该问题的更清晰的解决方案(除了使用动态之外)将是一个基本的非泛型接口:
并且您需要将该代码中使用的方法签名从 IFunnyInteface 移动到 IFunnyInterfaceBase。
这样你就可以写这样的东西:
你说你在代码中得到的异常不是由于扩展方法签名本身(该方法很好)..它是由你的左值的类型(类型用于存储其返回值的变量)!
显然,只有当您可以修改 IFunnyInterface 源代码时,此解决方案才适用!
thecoop answer points you exactly to why you can't do it.
A cleaner solution to the problem (besides using dynamic) would be a base non-Generics Interface:
And you need to move methods signature you use in that code from IFunnyInteface to IFunnyInterfaceBase.
This way you would be able to write something like this:
The Exception you said you got in your code is not due to the extension method signature itself (the method is fine)..it is originated by the type of your lvalue (the type of the variable you use to store its return value)!
Obviously this solution applies only if you can modify IFunnyInterface source code!