协变接口引用转换失败,为何不符合预期?
问题原因分析
你的转换失败的核心原因是:.NET泛型协变仅支持引用类型之间的引用转换,不支持值类型到引用类型的装箱转换。
具体解释
- 协变(
out修饰符)的本质是允许将泛型接口的派生类型参数实例,安全转换为基类型参数实例,但这个转换必须是引用转换——即转换前后引用的是同一个对象,不需要对类型参数本身进行装箱、拆箱或其他值类型转换。 - 你的场景中,
int是值类型,object是引用类型,int到object的转换属于装箱转换(会创建新的object实例包装int值),这不符合协变对引用转换的要求。因此CLR无法完成IColumn<Person, int>到IColumn<Person, object>的协变转换,抛出InvalidCastException。
验证示例
如果将TProp替换为引用类型(比如string),协变转换就能正常执行:
public class Person { public int Age { get; set; } public string Name { get; set; } } // 引用类型的协变转换正常工作 var column = new Column<Person, string>(p => p.Name); IColumn<Person, object> converted = column; // 无异常
补充说明
协变/逆变的设计目标是保持引用同一性,而值类型的装箱操作会生成新对象,打破了这一前提,因此值类型无法参与协变/逆变的跨类型转换。
内容的提问来源于stack exchange,提问作者Shahryar Saljoughi
相关产品推荐
相关产品推荐

