代码之家  ›  专栏  ›  技术社区  ›  CaffGeek

在共享相同接口的类之间强制转换

  •  7
  • CaffGeek  · 技术社区  · 14 年前

    我有两个接口 第二行 理想的人

    然后我有一个对象来实现 rawrow:iHeaderRow、ideTailRow

    然后我要把它扔给 头尾 实现 第二行 .

    但当我尝试的时候,它最终是空的或者给出了一个异常。

    我可以投 反对票 到任一接口 第二行 理想的人

    var ObjectIHeaderRow = ObjectRawRow as IHeaderRow;
    var ObjectIDetailRow = ObjectRawRow as IDetailRow;
    

    但我不能投 反对票 头尾 对象标题错误 头尾 .

    它抛出错误 无法将源类型“ia”转换为目标类型“a”

    我要把它投到实际的课堂上 头尾 .

    思想?

    编辑:

    尽管设立了一个明确的演员阵容来解决这个问题,但我想我会给那些想知道我为什么要做我自己的人一个答案。

    简而言之,我是按顺序处理一个文件。一行一行。我把这行读入rawrow,直到看到一些值,我才真正知道它将是什么类型的行。然后我想把它铸造成合适的类型。

    7 回复  |  直到 14 年前
        1
  •  6
  •   Jeff Sternal    14 年前

    您只能隐式地将对象强制转换为它们继承自或实现的类型-因为 RawRow 不是从 HeaderRow 不可能。

    根据您的要求,您可以通过编写 explicit conversion operator 创建一个 头尾 接受 罗罗 作为它的原型,或者通过修改代码在 IHeaderRow .

        2
  •  4
  •   unholysampler    14 年前

    你为什么要先把它扔给一个头儿?如果iHeaderRow生成了HeaderRow实现的API,那么您应该能够使用定义的方法对iHeaderRow“对象”执行操作。

    接口的要点是,您可以将不同对象的分组视为类似的类型。不是这样,您就可以在没有通过继承链接的类之间强制转换不同的对象。

        3
  •  2
  •   Tesserex    14 年前

    首先,你为什么要做这么奇怪的演员?对于你想做的事情,可能还有另一种设计。

    第二,你不能做这个演员的原因是因为一个RAWROW 不是 头尾它唯一的保证就是它能实现 IHeaderRow . 问题是它也有很多其他的东西 HeaderRow 没有。反之亦然- 头尾 可能有很多东西 ObjectRawRow 没有。

    想象一下你的课程是这样的:

    interface IHeaderRow
    {
        string GetText();
    }
    
    class HeaderRow : IHeaderRow
    {
        public string GetText()
        { 
            return "My Label";
        }
    
        public int GetFoo()
        {
            return 42;
        }
    }
    
    class ObjectRawRow : IHeaderRow
    {
        public string GetText()
        {
            return "My Raw Label";
        }
    }
    

    现在,如果你这样做,你就没事了:

    ObjectRawRow row = new ObjectRawRow();
    IHeaderRow header = row as IHeaderRow;
    string label = header.GetText();    // fine, since GetText is guaranteed to exist
    

    但试一下这个尺寸:

    ObjectRawRow row = new ObjectRawRow();
    HeaderRow header = row as HeaderRow;
    int magic = header.GetFoo();       // BOOM! Method doesn't exist,
    // because the object isn't really a HeaderRow under the covers.
    // It's still really an ObjectRawRow. What do you do now? Crash hard is what.
    

    这就是为什么你不能把它扔到继承树的外面。

        4
  •  1
  •   Amy B    14 年前

    除非一个继承自另一个,否则不能将ObjectRawrow强制转换为HeaderRow。

    接口与之无关。


    考虑:

    class Shape
    interface IHasCorners
    class Rectangle : IHasCorners, Shape
    class Triangle : IHasCorners, Shape
    
    
    Rectangle myRectangle = new Rectangle();
    Triangle myTriangle = new Triangle();
    
    //upcasts
    Shape s = (Shape)myRectangle;
    IHasCorners hc = (IHasCorners)myRectangle;
    
    //downcasts
    Rectangle r2 = (Rectangle)s;
    r2 = (Rectangle)hc;
    
    //upcasts
    s = (Shape)myTriangle;
    hc = (IHasCorners) myTriangle;
    
    //these downcasts won't work
    //the variables now reference a Triangle instance
    Rectangle r3 = (Rectangle)s;
    r3 = (Rectangle)hc;
    
        5
  •  1
  •   Andrew Hare    14 年前

    除非类型之间存在继承关系,否则无法进行此强制转换。如果这不可能,那么最好创建一个显式转换运算符,允许您将一个类型转换为另一个类型。

    如果确实创建了显式转换,您应该理解这将比强制转换慢,因为您将调用一个可以工作的方法,而不是强制转换,后者只更改引用类型,不会更改堆上的任何内存。

    考虑这个不编译的示例:

    class Example
    {
        static void Main()
        {
            Foo foo = new Foo();
            Bar bar = (Bar)foo;
        }
    }
    
    class Foo { }
    class Bar { }
    

    因为类型之间没有继承关系,也没有从 Foo Bar 这无法编译。

    但是添加显式转换允许它编译:

    class Example
    {
        static void Main()
        {
            Foo foo = new Foo();
            Bar bar = (Bar)foo;
        }
    }
    
    class Foo
    {
        public static explicit operator Bar(Foo foo)
        {
            return new Bar();
        }
    }
    class Bar { }
    
        6
  •  0
  •   SLaks    14 年前

    如果对象实际上是某个类的实例(或从该类派生),则只能将实例强制转换为该类。

    不可能将类A的实例强制转换为完全不相关的类B(这正是您要做的),即使它们实现相同的接口。

        7
  •  0
  •   Joel    14 年前

    你可以使用 explicit keyword 创建在尝试从中强制转换时将调用的方法 IA A . 如果不编写自己的方法,它就无法工作,原因是编译器不知道如何处理未提供的值。