[英]Put a struct as a generic covariant parameter
I've an Covariant interface, which is in an array of it's parent type.我有一个 Covariant 接口,它位于它的父类型的数组中。 They are defined globally like this:它们在全局定义如下:
//The interface/class
public interface IMyType<out T>{}
public class MyType<T>: IMyType<T>{
T value;
MyType<T>(T initialValue){
value = initialValue;
}
}
I tried this:我试过这个:
IMyType< object>[] tt = new IMyType<object>[]
{
new MyType<String>( "test"), //Works fine
new MyType<SomeOtherRandomClass>(new SomeOtherRandomClass()),//works fine
new MyType<Int32>(12)//Doesn't work
};
Even trying to specify a struct instead of object:甚至试图指定一个结构而不是对象:
IMyType< struct>[] tt = new IMyType<struct>[]//Doesn't work:Incorrect Number of parameter
{
new MyType<Int32>(12)//Doesn't work
};
Specifying only a specific struct works:仅指定特定结构有效:
IMyType< int>[] tt = new IMyType<int>[]//Does work
{
new MyType<Int32>(12)//Does work
};
So why does this not work?那么为什么这不起作用呢? Is there a way to make it work?有没有办法让它工作?
It is completely impossible to convert an Interface<ValueType>
to Interface<object>
as a covariant conversion.将Interface<ValueType>
转换为Interface<object>
作为协变转换是完全不可能的。
The reason for this is that the JITter must compile a separate version of your class for each value type (since value types have different shapes), so it cannot convert it to any other generic instantiation.这样做的原因是 JITter 必须为每个值类型编译一个单独的类版本(因为值类型具有不同的形状),因此它不能将它转换为任何其他通用实例化。
Variance only works for reference types because references are all the same, so the JITted methods can be shared across different type parameters.方差仅适用于引用类型,因为引用都是相同的,因此 JITted 方法可以在不同的类型参数之间共享。
Your best solution may be to write a wrapper class that encapsulates a struct:您最好的解决方案可能是编写一个封装结构的包装类:
public class StructContainer<TStruct> where TStruct : struct
{
TStruct value;
public StructContainer(TStruct initialValue)
{
value = initialValue;
}
}
Then you could do:那么你可以这样做:
IMyType<object>[] tt = new IMyType<object>[]
{
new MyType<String>("test"), //Works fine
new MyType<StructContainer<int>>(
new StructContainer<int>(12)
) // compiles now
};
Granted, this sacrifices the simplicity of your original syntax and forces you to do hokey things (like type checks) later on when you need to pull items out of your collection.诚然,这牺牲了原始语法的简单性,并迫使您稍后在需要从集合中提取项目时做一些复杂的事情(如类型检查)。
One other option is to track a collection of objects AND a collection of structs as separate collections.另一种选择是将对象集合和结构集合作为单独的集合进行跟踪。 This may make more sense because, again, once you pull items out of your list, it's likely that you'll need to treat them differently anyway.这可能更有意义,因为同样,一旦您将项目从列表中拉出,您可能需要以不同的方式对待它们。
If you want to accomplish putting generic types with different type parameters into the same collection, and you can't use covariance for the reason SLaks mentioned, then you should have the generic type implement a non-generic interface:如果你想完成将具有不同类型参数的泛型类型放入同一个集合中,并且由于 SLaks 提到的原因你不能使用协方差,那么你应该让泛型类型实现一个非泛型接口:
public interface IMyType<out T> : ISomeBaseInterface {}
var tt = new ISomeBaseInterface[]
{
new MyType<String>( "test"), //Works fine
new MyType<SomeOtherRandomClass>(new SomeOtherRandomClass()),//works fine
new MyType<Int32>(12)//now it works
};
This may or may not be sufficient depending on what your other requirements are.根据您的其他要求,这可能足够也可能不够。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.