2011-12-20 7 views
7

私は(VSデバッガの下で実行)、次のコードが動作する理由として興味:intはなぜですか?インスタンスプロパティがnullに設定されていますか?

int? x = null; 
null 
x.HasValue 
false 

xが実際にnullの場合、どのようなインスタンスはにHasValue指すのでしょうか?拡張メソッドとしてHasValueが実装されていますか、それともコンパイラが特別な場合にこれを魔法のように動作させるのですか?

+1

nullable型の本当に恐ろしい特別なケースがあります。ボクシングの実行時にランタイムは自動的に内部値を逆参照します。これは、 "((オブジェクト)x).HasValue"がNullReferenceExceptionをスローすることを意味します。それは恐ろしいことだ。 –

+0

@KennetBelenky実際に '((object)x).HasValue'はオブジェクトにHasValueプロパティがないのでコンパイルされません。私は '((オブジェクト)x).ToString()'(または '.GetHashCode()'や '.Equals(something)')がスローすると言っていたと思います。 – phoog

+0

@phoog、oops私は私の説明で少し急いでいた。あなたは正しい、私の説明は構文的に無効です。しかし、Nullableをオブジェクトにキャストした瞬間、それはもはやNullableではありません。 .Netフレームワークの他の型はそのプロパティを持ちません。 –

答えて

9

xは参照型ではありません。 ?は、Nullable<T>の構文糖で、struct(値タイプ)です。

+0

これは最も理にかなっています。比較演算子と代入演算子にも過負荷がかかります。しかし、私を混乱させることは、ウォッチウィンドウの下で 'x 'を見ると、' null'を示しています(これが本当に値型の場合は不可能です)。 VSデバッガはこれを特別なケースですか? –

+0

@Mike:まあ、VSデバッガは奇妙な獣です。しかし、私はこの場合、単純にNullableの 'ToString()'メソッドを使用していると思います。 – Cameron

+0

@Cameron、ToString()は、値がnullと等しい場合に、emtpy文字列を返すようにnullableが記述されています。もし私がニッケルを賭けなければならなかったら、私はデバッガがそれをボクシングしていると言うでしょう、それはnullを生成します。 –

1

int? x = null次いでxを用いNullable<int>の新しいインスタンスが割り当てられ、IST値をnullに設定されています。

私は内部構造を正確には知りませんが、代入演算子自体に多少のオーバーロードがあると想定します。

5

int?は、実際には構造Nullable<int>です。したがって、これは常に構造体のインスタンスであるため、xをnullにすることはできません。

0

nullable型(この場合はnullable int)はHasValueのプロパティがbooleanです。 HasValueがTrueの場合、Valueプロパティ(Type T、この場合はint)には有効な値が設定されます。それはまだ値型nullすることができないという事実を中心に取得していないので、

1

NULL可能なタイプは、実際にnullではありません。代わりに、Nullable<>構造体への参照(これは値型であり、nullにはできません)です。

詳細情報here

基本的に、null可能な型を使用するときは、何かのインスタンスを参照しています。その参照によって返されるデフォルトの情報は、格納された値です(格納された値がない場合はnull)。

1

null可不可実際には参照型であり、そのインスタンスメソッドは、これが表示される場所の1つです。基本的には、boolean型のフラグを含むstruct型であり、その型の値はのnullableです。特殊なケースのさまざまな演算子(いくつかのケースではnullをfalseにする(bool?)を考慮する)とnullのリテラル、ランタイムの特殊ケースのボクシングですが、単なるstructです。

1

全く新しいタイプです。 NULL可能ではない T.

何を持っていることは、一般的なクラスのようなものです次のとおりです。私は特にゲッターとセッターで(それよりはそこだと確信してい

public struct Nullable<T> 
{ 
    public bool HasValue { get { return Value != null; } } 
    public T Value { get; set; } 
} 

が、それはそれをです。一言で言えば

+1

明示的な演算子もありますが、これは基本的にはそれです。 Jon SkeetはDepth_の_C#に 'Nullable 'を説明するのにかなり良い仕事をしています。 –

+0

実際は、クラスではなく一般的な 'struct'です。 –

+0

- このコメントを無視する、Ninja'd、Doc Brownによる記事 – DaveShaw

4

手振って答え:。NULL可能構造体は魔法です

長い答えは:あなたがNULL可能構造体にnullを代入するとヌル値で表されているもの、実際にはありませんが、何をトンの後ろに起こるのでしょう彼のシーンは異なります。この場合

int? val = null; // what you wrote 
Nullable<Int32> val = new Nullable<Int32>(); // what is actually there 

、構造体のインスタンスは、デフォルト値はfalseにbool HasValueプロパティセットにT Valueセットを有するように作成されます。それは値が設定されている場合に応じて、Tまたはnullに直接Nullable<T>ボックスとして、ボックス化されたときに

あなたが実際にNullable<T>からヌル参照を取得するだけです。

2

nullにはいくつかの意味があります。

ポインタベースの方法で変数とメモリを提示するプログラミング言語(C#の参照を含みますが、いくつかの詳細を隠しています)は、 "これは何も指していません"です。

もう1つは「これは意味のある価値がありません」です。

参照型では、前者を後者を表すために使用します。 string label = nullは「意味のないラベル」を意味するかもしれませんが、まだそれは残っていますが、それでもまだ残っています何が起こっているのか、メモリ内のポイントと何を指しているのかについてはまだわかりません。それはnullない下回っていない限り(null文字列があるのと同じ方法でNullable<T>が提供するものですC#1.1

、「意味のある値」を言わないための手段でintDateTimeでそう、しかしレベルではありませんでしたboxed)。nullに割り当てられ、nullに等しいので、他のセマンティクスではnullでありnullですが、参照と値の型の実装の違いは何も指していません。

参照型nullの「何も指していない」という側面だけで、インスタンスメソッドの呼び出しを停止します。

実際、厳密にはそうではありません。 ILはnull参照でインスタンスメソッドを呼び出そうとします。フィールドと対話しない限り、動作します。それが必要ならば、彼らはヌルrefernce上に存在しないので、それは(直接または間接的に)それらのフィールドを動作しないことができるが、その方法は以下のように定義されている場合、それはnull.FineWithNull()を呼び出すことができます。それは決まったのC#で

int FineWithNull() 
{ 
    //note that we don't actually do anything relating to the state of this object. 
    return 43; 
} 

これを禁止するには、すべての.NETのルールではありません(F#では可能ですが、わかりませんが、管理されていないC++で許可されていて、非常にまれなケースで便利でした)。

+0

私はC#がメソッドがクラスの拡張メソッドである場合にこれを実際に許可すると信じています。間違いなく、 '+ 1'についての面白い要約! –

+0

@MikeChristensenあなたは正しいのですが、その場合は何が起きているのですか?C#では、静的メソッド呼び出しの最初の引数がヌルであることを許可しています。インスタンスメソッドと同じ構文で呼び出されます。 –

+0

@MikeChristensen C#では、ほとんどの呼び出しで 'callvirt' ILを使用することでヌルのメソッド呼び出しを許可しないという興味深いアイロニーがあります。' callvirt'にはヌルチェックが含まれています。 'call'が使われている時もありますし、値型が仮想メソッドをオーバーライドしたときもあります。ヌルにすることはできません。さらに引き出すこともできません。' call'は 'callvirt'と全く同じセマンティクスを持ちます。 。さて、これは、それ自体がバーチャルか非バーチャルかが 'callvirt'か' call'かどうかを判断する唯一の方法ではないことを示していますが、C#では使用がほぼ反対であるという皮肉なことです。 –

関連する問題