当结构是在 C# 中转换的通用对象的协变类型时,结构无法转换为对象的任何解决方法?
Posted
技术标签:
【中文标题】当结构是在 C# 中转换的通用对象的协变类型时,结构无法转换为对象的任何解决方法?【英文标题】:Any workarounds for structs failing to cast to object when the struct is the covariant type of a generic object being being casted in C#? 【发布时间】:2021-12-13 20:13:44 【问题描述】:假设我使用协变类型参数 (struct
) 实例化一个泛型类,然后我将新创建的对象转换为自身,并使用类型参数 object
代替 struct
,转换将失败尽管差异应该允许。
例子:
public class Succeeds
public struct Fails
var castSucceeds = (IEnumerable<object>)Enumerable.Empty<Succeeds>();
var castFails = (IEnumerable<object>)Enumerable.Empty<Fails>();
正如您从上面看到的那样,由于IEnumerable<T>
的泛型类型是协变的,所以这个转换有效,但是当尝试使用struct
而不是class
时它会失败。我怀疑失败与将结构转换为对象时需要装箱有关。
有什么办法可以解决这个问题还是我看错了?
【问题讨论】:
正如文档 (docs.microsoft.com/en-us/dotnet/standard/generics/…) 所说:方差仅适用于引用类型;如果为变体类型参数指定值类型,则该类型参数对于生成的构造类型是不变的。 Variance 不适用于明显的原因:未装箱的值类型和类具有完全不同的布局。未装箱的值类型实际上并没有实现接口,只有装箱的版本才实现。对泛型进行了特殊优化以避免装箱,但在内部它最终成为直接方法调用 【参考方案1】:根据Microsoft:
方差仅适用于引用类型;如果您指定值类型 对于变体类型参数,该类型参数对于 生成的构造类型。
尝试进行手动投射:
var castFails = Enumerable.Empty<Fails>().Cast<object>();
【讨论】:
谢谢,当我试图找出哪里出错时,我肯定错过了! 手动转换示例对我不起作用,因为我实际上并没有处理IEnumerable
以上是关于当结构是在 C# 中转换的通用对象的协变类型时,结构无法转换为对象的任何解决方法?的主要内容,如果未能解决你的问题,请参考以下文章
(56)C#里的协变(covariant)和逆变(contravariant)