Casting between classes that use the same interface

I have two IHeaderRow interfaces, and IDetailRow

Then I have an object that implements as RawRow: IHeaderRow, IDetailRow

Then I need to pass it to HeaderRow , which implements IHeaderRow .

But when I try, it ends with zero or gives an exception.

I can use ObjectRawRow for the IHeaderRow or IDetailRow interface

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

But I can not distinguish ObjectRawRow from HeaderRow or ObjectIHeaderRow to HeaderRow .

It throws an error. Cannot convert source type "IA" to target type "A"

I need to include it in the actual HeaderRow class.

Thoughts?

EDIT:

Despite the fact that setting the explicit throw took care of the problem, I thought that I would give an answer to people who are wondering WHY I did what it was.

In short, I process the file sequentially. Line by line. I read the line in RawRow, and until I look at a few values, I really don't know what type of line it will be. Then I wanted to classify it as appropriate.

+7
casting c # interface
source share
7 answers

You can only implicitly throw objects into types that they inherit or implement, since RawRow not derived from HeaderRow , this is not possible.

Depending on your requirements, you can overcome this by writing an explicit conversion statement, creating a HeaderRow constructor that accepts RawRow as its prototype, or by modifying your code to work with IHeaderRow .

+6
source share

Why would you throw it at HeaderRow first? If IHeaderRow created an api that implements HeaderRow, you should simply be able to work on the "objects" of IHeaderRow using specific methods.

An interface point is that you can consider grouping different objects as a similar type. Not so that you can distinguish between different objects between classes that are not inherited.

+4
source share

First, why do you need to make such a strange cast? There is probably another project for what you are trying to do.

Secondly, the reason you cannot cast is because RawRow is not a HeaderRow. The only guarantee he makes is that it implements IHeaderRow . The problem is that he has a bunch of other things, stuff that HeaderRow doesn't have. And vice versa - HeaderRow , probably there are a bunch of things that ObjectRawRow does not have.

Imagine your classes look like this:

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

Now, if you do, you are fine:

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

But try this for size:

 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 still really an ObjectRawRow. What do you do now? Crash hard is what. 

And therefore, you cannot expose outside the inheritance tree.

+2
source share

You cannot drop ObjectRawRow in a HeaderRow unless inherited from another.

Interfaces have nothing to do with this.


Consider:

 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
source share

You cannot do this if there is no inheritance relationship between the types. If this is not possible, the best thing you can do is create an explicit conversion operator that allows you to use one type as another type.

If you create an explicit conversion, you should understand that it will be slower than casting, because you will call a method that will work, and not a casting that only changes the type of link and does not change any memory on the heap.

Consider this example that does not compile:

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

Since there is no inheritance relationship between the types and no explicit conversion from Foo to Bar , this cannot compile.

But adding an explicit conversion allows you to compile:

 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
source share

You can only pass an instance to a specific class if the object is actually an instance of this class (or is derived from this class).

It is not possible to pass an instance of class A to a completely unrelated class B (this is what you are trying to do), even if they implement the same interfaces.

0
source share

You can use the explicit keyword to create methods that will be called when trying to cast from IA to A The reason why it is not working without you to write your own method, because the compiler does not know what to do with values ​​that are not provided.

0
source share

All Articles