代码之家  ›  专栏  ›  技术社区  ›  Andreas Niedermair

为什么这个演员不可能?

  •  4
  • Andreas Niedermair  · 技术社区  · 15 年前
    interface IFolderOrItem<TFolderOrItem> where TFolderOrItem : FolderOrItem {}
    
    abstract class FolderOrItem {}
    
    class Folder : FolderOrItem {}
    
    abstract class Item : FolderOrItem {}
    
    class Document : Item {}
    

    现在我正试着做这样的事情:

    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>
        }
    }
    

    有没有可能让它工作起来?

    4 回复  |  直到 12 年前
        1
  •  13
  •   Marc Gravell    15 年前

    Foo : Bar 是的 ISomething<Foo> : ISomething<Bar> ...

    在某些情况下,C#4.0中的差异可能是一种选择。或者,有时您可以使用泛型方法来做一些事情(但不确定它在这里是否有用)。


    interface IFolderOrItem {}
    interface IFolderOrItem<TFolderOrItem> : IFolderOrItem
        where TFolderOrItem : FolderOrItem { }
    

    通常,基本接口会有一个 Type ItemType {get;} 指示正在考虑的实际类型。然后使用:

    IFolderOrItem SelectedItem { get; set; }
    ...
    public void SomeMagicMethod()
    {
        this.SelectedItem = GetMagicDocument(); // no cast needed
        // not **so** bad
    }
    

    根据规范,这与§25.5.6(ECMA 334 v4)有关:

    25.5.6换算

    构造类型遵循相同的转换规则(§13) 非泛型类型也是如此。申请时 这些规则、基类和 构造类型的接口应

    之间不存在特殊转换 构造的引用类型,而不是 第13条中所述的。特别地, 引用类型不允许 共变体转换(§19.5)。这 List<B> 没有 转换(隐式或非隐式) 明确地)到 List<A> 即使 B A 列表<B> List<object>

    这很简单:如果转换为 列表<A> A. 进入 名单。然而,这将打破僵局 列表<B> 类型 ,否则会出现意外故障 分配到时可能发生

    这同样适用于接口。这改变了一个问题 一点

        2
  •  6
  •   Binary Worrier    15 年前

    就编译器而言, IFolderOrItem<Document> IFolderOrItem<Item>

    Document 可能继承 Item 但是 IFolderOrItem<文件>

    我依靠Marc或Jon发布C#spec相关部分的链接。

        3
  •  3
  •   Gorpik    15 年前

    问题在于,强制转换不适用于泛型参数,而是适用于整个类。文档继承自项,为true,但IFolderOrItem<文件>不从IFolderOrItem继承<项目>,与此也没有任何关系。

        4
  •  2
  •   tbolon    15 年前

    下面是一个了解其为何以这种方式工作的示例:

    假设IFolderOrItem公开了一个方法,例如voidadd(T元素)。

    从项到文档的转换无效,因为项不是文档。