9

C#コードでは、変数にアクセスする前に、変数がnullであるかどうかをすでにテストしています。

if (myInt.HasValue) {
  var yourInt = myInt;

  // do something with yourInt
}

私の質問:null許容プロパティをテストした後ではないかのように使用することと、次のプロパティを使用することには違いがありますか?

if (myInt.HasValue) {
  var yourInt = myInt.Value; // see the difference?

  // do something with yourInt
}

.Valueこれは単なる好みの問題ですか、それともnull許容オブジェクトがそのテストに合格した後でも使用する明確な理由またはパフォーマンスへの影響がありますか?

アップデート

2番目の例を拡張しました。すでにでテストしていますHasValueが、そこで.Value値にアクセスするために使用します。

更新2

sを使用するように例を更新しました。varこれは、コードでは実際にはint型を使用していないためです。悪い例については申し訳ありません。このコードでは、実際にはNHibernateCriteriaクエリ内のオブジェクト(query)を使用していExpression.Eq("thing", myInt)ます。

これはコンパイルエラーをスローしません。NHibernateを関与させずに、例を単純化して質問の根本に到達しようとしていました。これにより一部の回答が無効になった場合は申し訳ありません。を明示的に呼び出すのではなく、別のメソッドに値を検索させる場合に、パフォーマンスに影響があるかどうかを確認しようとしていました.Value

4

4 に答える 4

24

更新:この質問は、2012年12月20日の私のブログの主題でした。2013年12月下旬から1月上旬にかけて、この最適化についてさらに検討していきます。すばらしい質問をありがとうございます。


明示的に.Valueを呼び出すのではなく、別のメソッドに値を検索させる場合に、パフォーマンスに影響があるかどうかを確認しようとしていました。

まず、パフォーマンスに関する質問がある場合は、質問に答えることができるのはあなただけです。ストップウォッチを使用して双方向で試して、どちらが速いかを確認することで答えます。なぜ人々がStackOverflowでこの質問を頻繁に行うのかは私には謎です。「インターネットねえ、これが2頭の馬の写真です。どちらが速く走るのですか?」と言っているのとまったく同じです。どのように知る必要がありますか? それらを競争させれば、あなたは知っているでしょう。彼らはあなたの馬です。

第二に、あなたは一般的な意味で間違った質問をしている。問題は「パフォーマンスに打撃がありますか?」ではなく、「パフォーマンスに許容できない打撃がありますか?」です。繰り返しになりますが、私たちはあなたに何が受け入れられるか、受け入れられないかを知りません。

第三に、あなたは非常に具体的な意味で間違った質問をしている。ナノスケールの最適化に興味がある場合、ここで尋ねる正しい質問は、Value getterまたはGetValueOrDefaultメソッドを使用する方が速いですか?

答えは、通常、GetValueOrDefaultメソッドはValueよりも高速であるということです。なんで?違いは次の違いであるため:

if (this.HasValue) return this.value; else throw new Exception();

return this.value; 

違いは何ですか? ジッタは前者の方法をインライン化しない可能性が高いため、余分な呼び出しを間接的に行うために最大数ナノ秒のペナルティを支払うことになります。

数ナノ秒のペナルティが関係する場合は、(1)数マイクロ秒で実行されるプログラムを作成しておめでとうございます。(2)実際の違いがあるかどうかを確認するために、非常に注意深く測定する必要があります。ナノ秒はかなり小さいです。

于 2012-05-02T15:31:18.663 に答える
15

これは単なる好みの問題ですか、それとも明確な理由がありますか

int yourInt = myInt.Value;

HasValueの場合はスローしfalseます。

したがって、を体験したくない場合は、最初InvalidOperationExceptionに確認してくださいHasValue

ご了承ください

int yourInt = myInt;

int?toからの暗黙の変換がないため(コンパイル時の失敗)は合法ではありません(int値がnull;の場合、toをキャストするための妥当な値はありませんint?)。あなたは言うことができます:

int yourInt = (int)myInt;

ただし、にアクセスするのと同じように、myIntこれがスローされることに注意してください。nullValue

最後に、デフォルト値を受け入れても問題がない場合は、null合体演算子を使用して次のように言うことができます。

int yourInt = myInt ?? defaultValue;

これは次と同等です。

int yourInt;
if(myInt.HasValue) {
    yourInt = myInt.Value;
}
else {
    yourInt = defaultValue;
}

これはコンパイルエラーをスローしません。NHibernateを関与させずに、例を単純化して質問の根本に到達しようとしていました。これにより一部の回答が無効になった場合は申し訳ありません。.Valueを明示的に呼び出すのではなく、別のメソッドに値を検索させる場合に、パフォーマンスに影響があるかどうかを確認しようとしていました。

いいえ。特にデータベースが関係している場合、パフォーマンスはここではまったく関係ありません。これには意味のあるパフォーマンスの違いはまったくなく、ボトルネックになることはありません。最も明確なコードを書くだけです。率直に言って、私.Valueは最も明確であることがわかります。

于 2012-05-02T14:24:37.337 に答える
2

このコードは無効です:

if (myInt.HasValue) {
  int yourInt = myInt;

  // do something with yourInt
}

プロパティを使用したくない場合はValue、代わりに明示的なキャストを使用するか、null合体演算子を使用する必要がありますGetValueOrDefault

int yourInt = (int) myInt;

キャストは、とにかくプロパティへのアクセスとしてコンパイルされることになりValueます、IIRC。

そうです、値がnullでないことをテストした後でも、コンパイルするためだけに、値を基になる値に変換するために何かをする必要があります。コンパイラーは「可能性のあるヌル性」を分析しようとはしません(たとえば、アクセス間のスレッド化によって変更される可能性のあるインスタンス変数である場合を想像してください)。これは、null許容式で許可されていることの規則に従っているだけであり、null許容でない型への暗黙の変換は、許可されていることの1つではありません...

于 2012-05-02T14:26:46.967 に答える
-2

直接呼び出すことができない理由があります。がnullの場合、.Valueの値はどうなると思いますか。yourIntmyInt

デフォルト値(たとえば、0)にしたい場合は、のようなnull許容intでextensionmethodを作成できます.ValueOrDefault()

于 2012-05-02T14:29:02.513 に答える