Home All Groups Group Topic Archive Search About
Author
5 Apr 2007 5:40 PM
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.

Author
5 Apr 2007 5:46 PM
Jon Davis
No idea, but I'm curious as to whether this might work?

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

Jon

Show quoteHide quote
"Larry Smith" <no_spam@_nospam.com> wrote in message
news:%23QPfIm6dHHA.4636@TK2MSFTNGP03.phx.gbl...
> 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.
>
Are all your drivers up to date? click for free checkup

Author
5 Apr 2007 6:00 PM
Larry Smith
> 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.
Author
5 Apr 2007 6:01 PM
Bruce Wood
On Apr 5, 10:40 am, "Larry Smith" <no_spam@_nospam.com> wrote:
> 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
Author
5 Apr 2007 6:07 PM
Larry Smith
Show quote Hide quote
> 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.
Author
5 Apr 2007 6:36 PM
Jon Skeet [C# MVP]
Bruce Wood <brucew***@canada.com> wrote:

<snip>

> 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 :)

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet   Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
Author
6 Apr 2007 2:40 PM
Wiebe Tijsma
Larry Smith schreef:
Show quoteHide quote
> 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;
Author
6 Apr 2007 4:57 PM
Jon Skeet [C# MVP]
Wiebe Tijsma <newsREM***@CAPITALStijsma.com> wrote:
> > 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;

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;

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet   Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too

Bookmark and Share