interface IFolderOrItem<TFolderOrItem> where TFolderOrItem : FolderOrItem {}
abstract class FolderOrItem {}
class Folder : FolderOrItem {}
abstract class Item : FolderOrItem {}
class Document : Item {}
Run Code Online (Sandbox Code Playgroud)
现在我想这样做:
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>
}
}
Run Code Online (Sandbox Code Playgroud)
有没有可能让这个工作?
Mar*_*ell 13
如果我正确地读它...那么问题是,仅仅因为Foo : Bar,但这并不意味着ISomething<Foo> : ISomething<Bar>...
在某些情况下,C#4.0中的差异可能是一种选择.或者,有时您可以使用通用方法执行某些操作(但不确定它在这方面会有所帮助).
你在C#3.0(及以下)中最接近的可能是一个非通用的基本接口:
interface IFolderOrItem {}
interface IFolderOrItem<TFolderOrItem> : IFolderOrItem
where TFolderOrItem : FolderOrItem { }
Run Code Online (Sandbox Code Playgroud)
通常,基本接口将具有例如a Type ItemType {get;}来指示所考虑的实际类型.然后用法:
IFolderOrItem SelectedItem { get; set; }
...
public void SomeMagicMethod()
{
this.SelectedItem = GetMagicDocument(); // no cast needed
// not **so** bad
}
Run Code Online (Sandbox Code Playgroud)
根据规范,这涉及§25.5.6(ECMA 334 v4):
25.5.6转换
构造类型遵循相同的转换规则(第13节)和非泛型类型.在应用这些规则时,构造类型的基类和接口应按照§25.5.3中的描述确定.
除了§13中描述的那些之外,构造的引用类型之间不存在特殊转换.特别是,与数组类型不同,构造的引用类型不允许共变转换(第19.5节).这意味着类型
List<B>没有转换(隐式或显式),List<A>即使B派生自A.同样地,没有转化率从存在List<B>到List<object>.[注意:这个的基本原理很简单:如果
List<A>允许转换 ,那么显然,可以将类型的值存储A到列表中.但是,这会破坏不变量,即类型列表中的每个对象List<B>始终是类型的值B,否则在分配到集合类时可能会发生意外故障.结束说明]
这同样适用于接口.这改变了一个位在C#4.0,但只在某些情况下.
就编译器而言,IFolderOrItem<Document>&IFolderOrItem<Item>是两种完全不同的类型.
Document可以继承Item,但IFolderOrItem<Document>不继承IFolderOrItem<Item>
我依靠Marc或Jon发布指向C#规范相关部分的链接.