Why is this invalid

  • Thread starter Thread starter Larry Smith
  • Start date Start date
L

Larry Smith

IDerived1 derived1 = GetDerived1();
IDerived2 derived2 = GetDerived2();
IBase ibase = (derived1 != null ? derived1 : derived2);

Where "IDerived1" and "IDerived2" each inherit from "IBase". The followinge
error results on the last line:

Error 32 Type of conditional expression cannot be determined because there
is no implicit conversion between 'Test.IDerived1' and 'Test.IDerived2'

I understand the error but why does the language consider it a problem in
this context. Thanks.
 
No idea, but I'm curious as to whether this might work?

IBase ibase = (derived1 != null ? (IBase)derived1 : (IBase)derived2);

Jon
 
No idea, but I'm curious as to whether this might work?
IBase ibase = (derived1 != null ? (IBase)derived1 : (IBase)derived2);

It does but I don't see why it has to be explicit.
 
IDerived1 derived1 = GetDerived1();
IDerived2 derived2 = GetDerived2();
IBase ibase = (derived1 != null ? derived1 : derived2);

Where "IDerived1" and "IDerived2" each inherit from "IBase". The followinge
error results on the last line:

Error 32 Type of conditional expression cannot be determined because there
is no implicit conversion between 'Test.IDerived1' and 'Test.IDerived2'

I understand the error but why does the language consider it a problem in
this context. Thanks.

Because C# determines expression types independently of where that
expression is ultimately to be assigned.

In other words, the compiler sees this:

IDerived1 derived1 = GetDerived1();
IDerived2 derived2 = GetDerived2();
(derived1 != null ? derived1 : derived2);

and has no idea whether the result of the expression should be
IDerived1 or IDerived2 (or something else). It hasn't noticed (yet)
that you're going to assign the result to an IBase reference variable.
It just knows that the two parts of the expression have two different
types that have no available conversion.

Jon's solution is the correct one, although you don't need to cast
them both (assuming that IBase is the base interface for both
IDerived1 and IDerived2). If you cast just one, the compiler will
understand that it has to cast the other to the base type in order to
make the expression work:

derived1 != null ? (IBase)derived1 : derived2
 
Because C# determines expression types independently of where that
expression is ultimately to be assigned.

In other words, the compiler sees this:

IDerived1 derived1 = GetDerived1();
IDerived2 derived2 = GetDerived2();
(derived1 != null ? derived1 : derived2);

and has no idea whether the result of the expression should be
IDerived1 or IDerived2 (or something else). It hasn't noticed (yet)
that you're going to assign the result to an IBase reference variable.
It just knows that the two parts of the expression have two different
types that have no available conversion.

Jon's solution is the correct one, although you don't need to cast
them both (assuming that IBase is the base interface for both
IDerived1 and IDerived2). If you cast just one, the compiler will
understand that it has to cast the other to the base type in order to
make the expression work:

derived1 != null ? (IBase)derived1 : derived2

Ok, thanks. I'm not a C# specialist but coming from the C++ world I see no
(immediate) reason for this restriction.
 
Because C# determines expression types independently of where that
expression is ultimately to be assigned.

At least, mostly :) It's a noble ideal, but (unfortunately?) the types
of anonymous methods and (in C# 3) lambda expressions depend on how
they're used.

Still, I'm glad it's mostly true :)
 
Larry Smith schreef:
IDerived1 derived1 = GetDerived1();
IDerived2 derived2 = GetDerived2();
IBase ibase = (derived1 != null ? derived1 : derived2);

Where "IDerived1" and "IDerived2" each inherit from "IBase". The followinge
error results on the last line:

Error 32 Type of conditional expression cannot be determined because there
is no implicit conversion between 'Test.IDerived1' and 'Test.IDerived2'

I understand the error but why does the language consider it a problem in
this context. Thanks.

An alternative in C# 2.0 is:

IBase ibase = derived1 ?? derived2;
 
Wiebe Tijsma said:
An alternative in C# 2.0 is:

IBase ibase = derived1 ?? derived2;

That has exactly the same issue as the original code. Try the
following:

class Base {}

class Derived1 : Base {}

class Derived2 : Base {}

class Test
{
static void Main()
{
Derived1 derived1 = null;
Derived2 derived2 = null;

Base foo = derived1 ?? derived2;
}
}

The "fix" is to cast either derived1 or derived2 to Base:
Base foo = derived1 ?? (Base)derived2;
or
Base foo = (Base)derived1 ?? derived2;
 
Back
Top