C# 为什么这个演员不可能? 接口IFolderOrItem,其中TFolderOrItem:FolderOrItem{} 抽象类FolderOrItem{} 类文件夹:FolderOrItem{} 抽象类项:FolderOrItem{} 类文档:项{}
现在我正试着做这样的事情:C# 为什么这个演员不可能? 接口IFolderOrItem,其中TFolderOrItem:FolderOrItem{} 抽象类FolderOrItem{} 类文件夹:FolderOrItem{} 抽象类项:FolderOrItem{} 类文档:项{},c#,generics,oop,C#,Generics,Oop,现在我正试着做这样的事情: interface IFolderOrItem<TFolderOrItem> where TFolderOrItem : FolderOrItem {} abstract class FolderOrItem {} class Folder : FolderOrItem {} abstract class Item : FolderOrItem {} class Document : Item {} 分类 { IFolderItem Select
interface IFolderOrItem<TFolderOrItem> where TFolderOrItem : FolderOrItem {}
abstract class FolderOrItem {}
class Folder : FolderOrItem {}
abstract class Item : FolderOrItem {}
class Document : Item {}
分类
{
IFolderItem SelectedItem{get;set;}
void SomeMagicMethod()
{
this.SelectedItem=(IFolderOrItem)GetMagicDocument();
//糟糕??
}
IFolderOrItem GetMagicDocument()
{
返回someMagicDocument;//类型为IFolderOrItem
}
}
有没有可能让它工作?就编译器而言,
IFolderOrItem
&IFolderOrItem
是两种完全不同的类型
文档
可以继承项
,但IFolderOrItem
不继承IFolderOrItem
我依靠Marc或Jon发布到C#spec相关部分的链接。问题是cast不能处理泛型参数,而是处理整个类。文档继承自项,true,但IFolderOrItem
Foo:Bar
,这并不意味着ISomething:ISomething
在某些情况下,C#4.0中的差异可能是一种选择。或者,有时您可以使用泛型方法来做一些事情(但不确定它在这里是否有用)
在C#3.0(及以下版本)中,最接近的可能是非通用的基本接口:
class Something
{
IFolderItemOrItem<Item> SelectedItem { get; set; }
void SomeMagicMethod()
{
this.SelectedItem = (IFolderOrItem<Item>)GetMagicDocument();
// bad bad bad ... ??
}
IFolderOrItem<Document> GetMagicDocument()
{
return someMagicDocument; // which is of type IFolderOrItem<Document>
}
}
根据规范,这与§25.5.6(ECMA 334 v4)有关: 25.5.6换算 构造类型遵循相同的转换规则(§13) 非泛型类型也是如此。申请时 这些规则、基类和 构造类型的接口应 如§25.5.3所述确定 之间不存在特殊转换 构造的引用类型,而不是 第13条中所述的。特别地, 与数组类型不同,构造 引用类型不允许 共变体转换(§19.5)。这 表示类型
列表
没有
转换(隐式或非隐式)
明确)到列表
,即使B
是
源自A
。同样地,没有
从列表
到
列表
[注:理由如下:
这很简单:如果转换为
列表
是允许的,那么显然,
可以将A
类型的值存储到
但是,这个列表将被打破
一个空间中每个对象的不变量
类型列表list
始终是一个值
类型为B
,或其他意外故障
分配到时可能发生
收集类别.结束注]
这同样适用于接口。这在C#4.0中有一点变化,但仅在某些情况下发生。一个例子来理解它为什么会以这种方式工作: 假设IFolderOrItem公开了一个方法,例如voidadd(T元素) IFolderOrItem的实现将假定参数是一个文档 但是如果您将IFolderOrItem转换为ifolderItem,那么有人可以调用Create(T)方法,其中T应该是一个项 从项到文档的转换无效,因为项不是文档
要做到这一点,唯一的方法是创建非通用版本的接口,允许对象作为参数,检查实现中对象的类型。它抛出的错误消息是什么?编译时?不带强制转换=编译时;使用cast=runtime(根据您在我的回复中的评论,我在一个非通用的基本接口上添加了一些注释,至少可以让它工作起来)@downvoter:这会很有趣,为什么……哈哈——但我相信这是C#3.0规范中没有的东西之一,因为这不是一个考虑因素。不过,4.0规范中应该有一些东西。很棘手。。。它不是一个IFolderOrItem,所以除非你包装它,否则它不会工作。根据接口中的成员,它可能在4.0中起作用(使用额外的修改器)。除此之外。。。也许声明一个非泛型接口…您的泛型自由接口与抽象类(泛型自由接口+泛型接口)结合的解决方案正好击中要害。。。哇!非常感谢。
interface IFolderOrItem {}
interface IFolderOrItem<TFolderOrItem> : IFolderOrItem
where TFolderOrItem : FolderOrItem { }
IFolderOrItem SelectedItem { get; set; }
...
public void SomeMagicMethod()
{
this.SelectedItem = GetMagicDocument(); // no cast needed
// not **so** bad
}