2011-10-20 8 views
4

次のコードは、Main関数の2行目のタイトルのエラーを示しています。オペレータ '??'子クラスの型のオペランドには適用できません

public class P {} 

public class B : P {} 

public class A : P {} 

void Main() 
{ 
    P p = GetA()??GetB(); 
} 

public A GetA() 
{ 
    return new A(); 
} 

public B GetB() 
{ 
    return new B(); 
} 

これら

p = (P)GetA()??GetB(); 
    or 
    p = GetA()??(P)GetB(); 

作品のような行に簡単に微調整。

私は、コンパイラが両方とも左側のコンテナの子クラスであり、キャストなしの操作を許可していることを理解していないのはなぜですか?

答えて

6

左側の引数の型は、右側の型の型と互換性がなければなりません。つまり、BからAまたはAからBへの暗黙的な変換が存在する必要があります。上記で

var a = x ?? y; 

yからxへの暗黙の変換が存在する場合、次いでxの種類は、式の型となります。 yからxへの暗黙的な変換はないが、xからyへの暗黙的な変換がある場合は、yのタイプが表現のタイプになります。どちらの方向にも変換がない場合は、ブームとなります。コンパイルエラー。仕様から:

式のタイプは? bは、どの暗黙的な変換がオペランドの型間で利用可能であるかに依存する。好みの順に、?? bはAの型であり、Bはbの型であり(ただし、bは型を持つ)、A0はnullの型であればAの基底型であり、そうでなければAである。 。具体的には、 bは次のように処理されます。

•AがNULL可能型または参照型でない場合、コンパイル時エラーが発生します。

•AがNULL可能型で、bからA0への暗黙の変換が存在する場合、結果の型はA0です。実行時に、まずaが評価されます。 aがNULLでない場合、aはA0をタイプするためにラップされ、これが結果になります。それ以外の場合は、bが評価されてA0型に変換され、これが結果になります。

•それ以外の場合、暗黙の変換がbからAに存在する場合、結果の型はAです。実行時に、最初にaが評価されます。 aがNULLでない場合、aが結果になります。さもなければ、bが評価され、タイプAに変換され、これが結果になります。

•それ以外の場合、bの型がBで暗黙の変換がA0からBまで存在する場合、結果の型はBです。実行時には、まずaが評価されます。 aがNULLでない場合、aは(AとA0が同じ型でない限り)型A0に展開され、型Bに変換され、これが結果になります。それ以外の場合は、bが評価され結果になります。

•それ以外の場合、aとbは互換性がなく、コンパイル時エラーが発生します。

+0

ああを、私は非常に複雑コメント私は時に再読み込みあなたの例を書くの過程にあったとLHSのタイプがあることに気づきましたRHSでの表現の評価から導かれた。最初は、「x」と「y」の両方が「a」に変換できる限り、それはすべて良いと思った! – Joe

+0

ええ、割り当てられる変数のタイプを含めて、最も直接的な方法であり、私はそれが最初にうまくいくと思いました。このように設計された理由については、エリック・リッペルトのような人から聞いてみたいと思います。 –

-1

オペレータのオペランド?同じタイプである必要があります。

P a = GetA(); 
    P b = GetB(); 
    P p = a ?? b; 
+1

これらは同じ型である必要はなく、単に暗黙の変換*が存在しなければなりません。 –

1

コンパイラは両方とも左側のコンテナの子クラスであることを理解し、キャストせずに操作を許可しない理由は、私が興味?

、これは許可されますので:私は見

public class SqlConnection : object {}  
public class Random : object {} 

public SqlConnection GetA() { return new SqlConnection(); } 
public Random GetB() { return new Random(); } 

void Main() 
{ 
    var p = GetA() ?? GetB(); 
} 
+0

+1私は例が好きです:) –

+0

ハム...しかし、ハングアップ! 'var p =(オブジェクト)GetA()?? GetB(); 'は許可されています。それは構文的に異なるかもしれないが、同じ論理目的を達成する。 – Joe

+0

@ジョー:オブジェクトに何かをキャストすることができます.Bからオブジェクトへの暗黙的な変換があるので、結果の式はobjectを返します。ここでvarを使用すると、キャストを実行する場合、pがオブジェクト型になるため、この例は傷つきます。 –

関連する問題