Кастинг между классами, которые совместно используют тот же интерфейс

У меня есть два интерфейса IHeaderRow и IDetailRow

У меня затем есть объект, который реализует обоих RawRow:IHeaderRow, IDetailRow

Я затем должен бросить его в HeaderRow, который реализует IHeaderRow.

Но когда я пробую, это заканчивает тем, что было пустым или дало исключение.

Я могу бросить ObjectRawRow или к интерфейсу IHeaderRow или к IDetailRow

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

Но я не могу бросить ObjectRawRow в HeaderRow или ObjectIHeaderRow в HeaderRow.

Это бросает ошибку, не Может преобразовать исходный тип 'IA' для предназначения для типа

Я должен бросить его в фактический класс HeaderRow.

Мысли?

Править:

Даже при том, что установка явного броска заботилась о проблеме, я думал, что предоставлю ответ людям, задающимся вопросом, ПОЧЕМУ я делал, кто я был.

Короче говоря, я последовательно обрабатываю файл. Линию за линией. Я считал строку в RawRow, и пока я не смотрю на несколько значений, я на самом деле не знаю, какой строкой это будет. Я затем хотел бросить его к надлежащему типу.

8
задан CaffGeek 15 April 2010 в 21:33
поделиться

7 ответов

Вы можете только неявно приводить объекты к типам, которые они наследуют или реализуют - поскольку RawRow не является производным от HeaderRow , это невозможно.

В зависимости от ваших требований, вы можете преодолеть это, написав оператор явного преобразования , создав конструктор HeaderRow , который принимает RawRow в качестве своего прототипа, или путем изменения кода для работы с IHeaderRow .

6
ответ дан 5 December 2019 в 12:09
поделиться

Вы не можете преобразовать 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;
1
ответ дан 5 December 2019 в 12:09
поделиться

Почему вам вообще нужно преобразовать его в HeaderRow? Если IHeaderRow создал api, который реализует HeaderRow, тогда вы должны просто иметь возможность воздействовать на «объекты» IHeaderRow, используя определенные методы.

Смысл интерфейса в том, что вы можете рассматривать группу различных объектов как один и тот же тип. Не то чтобы вы могли преобразовывать разные объекты между классами, не связанными наследованием.

4
ответ дан 5 December 2019 в 12:09
поделиться

Во-первых, зачем вам такое странное приведение? Вероятно, есть другой дизайн для того, что вы пытаетесь сделать.

Во-вторых, вы не можете выполнить приведение по той причине, что RawRow не HeaderRow. Единственная гарантия, которую он дает, - это то, что он реализует IHeaderRow . Проблема в том, что в нем есть еще куча других вещей, которых нет в HeaderRow . И наоборот - 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.

И вот почему вы не можете преобразовать за пределы дерева наследования .

2
ответ дан 5 December 2019 в 12:09
поделиться

Вы можете привести экземпляр к определенному классу только в том случае, если объект на самом деле является экземпляром этого класса (или является производным от этого класса).

Невозможно привести экземпляр класса A к полностью несвязанному классу B (что вы и пытаетесь сделать), даже если они реализуют одни и те же интерфейсы.

0
ответ дан 5 December 2019 в 12:09
поделиться

Вы можете использовать явное ключевое слово для создания методов, которые будут вызываться при попытке приведения из IA к A . Причина, по которой он не работает без написания собственного метода, заключается в том, что компилятор не знает, что делать со значениями, которые не предоставляются.

0
ответ дан 5 December 2019 в 12:09
поделиться

Вы не сможете выполнить это приведение, если между типами нет отношения наследования. Если это невозможно, лучшее, что вы можете сделать, - это создать оператор явного преобразования, который позволяет преобразовать один тип в другой.

Если вы действительно создаете явное преобразование, вы должны понимать, что это будет медленнее, чем преобразование, поскольку вы будете вызывать метод, который будет работать, в отличие от преобразования, которое изменяет только ссылочный тип и не меняет никакой памяти. в куче.

Рассмотрим этот пример, который не компилируется:

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 { }
1
ответ дан 5 December 2019 в 12:09
поделиться
Другие вопросы по тегам:

Похожие вопросы: