Forum: PC-Programmierung C# und ternärer Operator


von Alex (Gast)


Lesenswert?

Warum funktioniert in C# ...

MyBaseClass foo(bool bar)
{
    if (bar) return new MyDerivedClass1();
    else return new MyDerivedClass2();
}

... aber nicht ...

MyBaseClass foo(bool bar)
{
    return bar ? new MyDerivedClass1() : new MyDerivedClass2();
}

... ???

Fehlermeldung:

Type of conditional expression cannot be determined because there is no 
implicit conversion between 'MyDerivedClass1' and 'MyDerivedClass2'

Gruß,
Alex

von Klaus W. (mfgkw)


Lesenswert?

Im ersten Fall muß nur bei jedem return zur Basisklasse gecastet werden,
das geht immer.

Im zweiten Fall dagegen weiß der Compiler noch nicht (bzw. weigert
sich, es zu sehen), daß letztlich etwas in der Basisklasse rauskommen
soll, während er über den Auswahloperator nachdenkt. Für den aber
müssen die beiden Operanden zueinander kompatibel sein, zwei
verschiedene Ableitungen einer Basisklasse sind das von sich aus
nicht. Erst das Ergebnis von ?: würde in die Basisklasse gecastet
werden wegen des return, aber da ist es schon zu spät.

von Klugscheißer (Gast)


Lesenswert?

Versuch mal
return bar ? ( MyBaseClass)new MyDerivedClass1() : ( MyBaseClass)new 
MyDerivedClass2();

von Markus (Gast)


Lesenswert?

C# ist typstreng. Der Operator ?: hat genau einen Ergebnistyp. Welchen 
soll er denn in Deinem Fall nehmen? MyDerivedclass1, MyDerivedclass2 
oder MyBaseClass?

Wie Klugscheißer bereits geschrieben hat, kannst Du das Problem mit 
einem expliziten Type-Cast lösen. Oder aber Du machst, was der Compiler 
bemängelt: Implementiere doch einfach die impliziten Casts!
1
class MyDerivedClass1 {
2
    ...
3
    public static implicit operator MyBaseClass( MyDerivedClass1 val ) {
4
        return val; // ggf. (MyBaseClass)val
5
    }
6
    ...
7
}
8
9
class MyDerivedClass2 {
10
    ...
11
    public static implicit operator MyBaseClass( MyDerivedClass2 val ) {
12
        return val; // ggf. (MyBaseClass)val
13
    }
14
    ...
15
}
16
17
class MyBaseClass {
18
    ...
19
    public MyBaseClass Foo( MyDerivedClass1 o1, MyDerivedclass o2 ) {
20
        ...
21
        return ( cond ) ? o1 : o2;
22
    }
23
    ...
24
}

Gruß
Markus

von Alex (Gast)


Lesenswert?

Hallo,

erstmal danke für die Infos!

@Markus
user-defined conversions to or from a base class are not allowed

Die Lösung mit dem Cast passt dafür. Im Prinzip sehe ich das 
Compilerverhalten an der Stelle aber als eher fragwürdig an. Für mich 
ist ein "?" nur die Kurzform von if-else, nicht mehr und nicht weniger 
...

von Klaus W. (mfgkw)


Lesenswert?

das if-else ist nur eine stark vereinfachte Darstellung;
es gibt mehrere Unterschiede.

von Arc N. (arc)


Lesenswert?

Alex schrieb:
> Hallo,
>
> erstmal danke für die Infos!
>
> @Markus
> user-defined conversions to or from a base class are not allowed
>
> Die Lösung mit dem Cast passt dafür. Im Prinzip sehe ich das
> Compilerverhalten an der Stelle aber als eher fragwürdig an. Für mich
> ist ein "?" nur die Kurzform von if-else, nicht mehr und nicht weniger
> ...

Vereinfacht gesagt:
? ist ein Ausdruck, der einen Wert zurückliefert
if ist kein Ausdruck, sondern eine Anweisung die keinen Wert 
zurückliefert (im Gegensatz z.B. zum if in Haskell, F#, Smalltalk etc)

von Rolf Magnus (Gast)


Lesenswert?

> Die Lösung mit dem Cast passt dafür. Im Prinzip sehe ich das
> Compilerverhalten an der Stelle aber als eher fragwürdig an.

Warum? Ich kenne C# nicht so, aber es ist wohl in der  Hinsicht wie C 
und C++, nämlich daß der Rückgabe-Typ eines Operators aussließlich von 
den übergebenen Argumenten abhängt und nicht davon, was man später mit 
dem zurückgegebenen Wert macht. Und in diesem Fall haben die beiden 
Argumente unterschiedlichen Typ, also müßte eins in den Typ des anderen 
konvertiert werden, was aber nicht geht, da keiner die Basisklasse vom 
anderen ist. Daß du nachher gern ein MyBaseClass hättest, ist dem 
Operator egal.

> Für michist ein "?" nur die Kurzform von if-else, nicht mehr und nicht
> weniger

Was es für dich ist, ist aber von relativ wenig Bedeutung.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.