Reputation: 443
I'm experiencing unexpected compiler errors with this code:
bool b = true; //or false
StringBuilder builder = ...; // a string builder filled with content
IVersePart vp = b ? (DualLanguageVersePart)builder : (VersePart)builder;
Both DualLanguageVersePart and VersePart implement the IVersePart interface. Both DualLanguageVersePart and VersePart have an explicit cast operator form StringBuilder.
Since both classes implement the interface that's the type of vp
, I would expect this to work flawlessly, or at least compile properly. Instead the compiler reports that no implicit conversion can be done between the two types.
Why is this not working?
Upvotes: 1
Views: 190
Reputation: 283664
The result type of any operator (other than operator implicit
) is determined by the operands and not by context.
Contrary to most of the wisdom being dispensed here, both arguments don't have to be the same type. If one type is derived from the other then the ternary operator result will be the base type. But in your example there are multiple common base types: at least Object
and IVersePart
, and the C# language doesn't make the compiler try to figure out which is better.
Upvotes: -1
Reputation: 103515
This is a bad design. Cast operators should not be used like that.
It would be better to have a ctor to handle this (as you are, in fact trying to construct a new object)
IVersePart vp = new DualLanguageVersePart(builder);
Alternately, you could use a factory:
IVersePart vp = VersePart.DualOrSingluar(builder, b);
Upvotes: 2
Reputation: 4867
The ternary operate requires the true and false to return the same type. Here's is one way to get around this, kind of sloppy though...
IVersePart vp = b
? (IVersePart)((DualLanguageVersePart)builder)
: (IVersePart)((VersePart)builder);
Upvotes: 0
Reputation: 62027
The ternary operator needs to be able to return one type, as it's just a single statement. So when you have the two parts of the operator returning different types, the compiler will attempt to allow this by quietly converting one to the other. You don't have a conversion from DualLanguageVersePart to VersePart, or vice versa.
One simple fix is to just add in a second cast to IVersePart
:
IVersePart vp = b ? (IVersePart)(DualLanguageVersePart)builder : (IVersePart)(VersePart)builder;
Upvotes: 0
Reputation: 67380
Both parts have to have the same type, so try this:
IVersePart vp = b ?
(IVersePart)(DualLanguageVersePart)builder :
(IVersePart)(VersePart)builder;
The C# compiler is fussier about this than the C++ compiler :)
Upvotes: 2
Reputation: 5967
I've had this issue before, ternary operator requires both types of the true result or false result either be the same type, or you cast them to the same type.
Upvotes: 1