質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Null

Nullとは、プログラミング言語やデータベースにおけるデータ表現の一種です。コンテキストによって"空"もしくは"長さ0の文字列"、”未知・不明”を意味します。

NullPointerException

null値の参照型変数を参照しようとした場合に投げられる、Javaにおける例外のひとつです。

.NET Framework

.NET Framework は、Microsoft Windowsのオペレーティングシステムのために開発されたソフトウェア開発環境/実行環境です。多くのプログラミング言語をサポートしています。

Q&A

4回答

24137閲覧

「== null」と「is null」でどちらの方が高効率か

Takym

総合スコア22

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Null

Nullとは、プログラミング言語やデータベースにおけるデータ表現の一種です。コンテキストによって"空"もしくは"長さ0の文字列"、”未知・不明”を意味します。

NullPointerException

null値の参照型変数を参照しようとした場合に投げられる、Javaにおける例外のひとつです。

.NET Framework

.NET Framework は、Microsoft Windowsのオペレーティングシステムのために開発されたソフトウェア開発環境/実行環境です。多くのプログラミング言語をサポートしています。

0グッド

1クリップ

投稿2019/03/08 03:22

タイトルにもありますが、C#で== nullis nullでどちらの方が高効率でしょうか?もし、このサイトの説明の様に、==演算子が継承されていて、nullと比較した時にtrueが返された場合大きな問題になります。なので、is nullSystem.Object.ReferenceEquals(object, object)等を利用して参照が確実にnullかどうか判定する必要があると思うのですが、保守性、速度等から見て全ての== nullis nullに変えるのは、効率的と言えますか?

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答4

0

C#

1using System; 2using System.Diagnostics; 3using System.Linq; 4 5namespace ConsoleApp1 6{ 7 class Program 8 { 9 static void Main(string[] args) 10 { 11 Console.WriteLine(new Nullable<int>() == null); 12 Console.WriteLine(new Nullable<int>() is null); 13 Console.WriteLine(ReferenceEquals(new Nullable<int>(), null)); 14 for (int i = 0; i < 3; i++) 15 { 16 MeasureTime("==", a => a == null); 17 MeasureTime("is", a => a is null); 18 } 19 Console.ReadKey(); 20 } 21 22 static void MeasureTime(string title, Func<int?, bool> action) 23 { 24 var stopwatch = new Stopwatch(); 25 stopwatch.Start(); 26 var result = Enumerable 27 .Range(0, 100000000) 28 .Select(a => (int?)a) 29 .Concat(new[] { default(int?) }) 30 .TakeWhile(a => !action(a)) 31 .Count(); 32 stopwatch.Stop(); 33 Console.WriteLine($"■ {title} ■"); 34 Console.WriteLine($"ループ回数: {result}"); 35 Console.WriteLine($"時間: {stopwatch.Elapsed}"); 36 } 37 } 38}

上記コードで計測してみたところ、うちでは次のようになりました。

True True True ■ == ■ ループ回数: 100000000 時間: 00:00:05.3188705 ■ is ■ ループ回数: 100000000 時間: 00:00:04.4728642 ■ == ■ ループ回数: 100000000 時間: 00:00:04.9455408 ■ is ■ ループ回数: 100000000 時間: 00:00:04.9704037 ■ == ■ ループ回数: 100000000 時間: 00:00:04.9747958 ■ is ■ ループ回数: 100000000 時間: 00:00:05.4253197

効率面から言えば、誤差の方が大きいので全く気にする必要はありません。

また、new Nullable<int>() に対して == is ReferenceEquals の全てが true を返しています。オブジェクトを作成しているので、当然 null ではないのになぜこうなるかと言うと、Nullable<T> は値型なので、比較関数に引数として渡される時に値のコピーが発生しますが、この時コピーの代わりに該当オブジェクトではなく null が渡されるからです。

したがって、Nullable<T> ではこの三つを区別する必要はありません。クラスによっては区別する必要がでてきますから、それはその時々の状況に合わせて考えてください。

投稿2019/03/08 04:10

Zuishin

総合スコア28660

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Takym

2019/03/08 04:28

ご回答ありがとうございます。 計測結果的に、効率については気にしなくても良いのですね。 状況に合わせて使い分ける事にします。
guest

0

こんにちは。

equalityのオーバーロードが実装されていない型を相手にする場合はどちらの記述でも全く同じ結果になります。
オーバーロードされているものを比較する場合は、比較処理が走らないis nullの方が低コストです。といっても、比較が非常にヘビーな実装でもない限り誤差すら出ない程度だと思いますが。

問題はそこではなくて、「あなたがどちらの結果を求めているのか」だと思います。
equalityのオーバーロードによって実装されたオブジェクト特有の比較による結果を利用したいなら==を使う以外の選択肢は無いですし、単純にnullではないことを確認したいならis nullの方が確実な結果を得られます。

例えば使用中のサードパーティライブラリが突然equalityをオーバーロードして、比較の結果が変わることを是とするか非とするかで決めないと後々訳が分からなくなります。
保守性、速度等を評価基準にする場合では基本的に書き換える価値は全くないと考えます。

投稿2019/03/08 04:08

tamoto

総合スコア4103

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Zuishin

2019/03/08 04:24

私の回答にあるように new Nullable<int>() is null は true になるので、これも確実とは言えないようです。このオブジェクトは HasValue プロパティを持ちますから null でないことは明らかです。
Takym

2019/03/08 04:26

ご回答ありがとうございます。 > 問題はそこではなくて、「あなたがどちらの結果を求めているのか」だと思います。 この文章で納得しました。
tamoto

2019/03/08 04:36

Zuishinさん> 確かにこれはそうですね。Nullableにおけるnullが「ゼロ値である」という意味と解釈して理解はできますけど、これはキモい……
Zuishin

2019/03/08 04:41

これが null と判定されないと null 合体演算子が使えなくなりますから仕方ないことなのだとは思いますが、落とし穴になるかもしれませんね。
tamoto

2019/03/08 04:44

Nullableが言語による特別サポートで`null`と`default`が全く同じものとして扱われている、ということをちゃんと理解していればそう難しくはないのですけど、どうみてもかなり罠です。。
Takym

2019/03/08 04:47

`HasValue`が`false`の時のみに`null`と同等という事ですよね? `HasValue`が`true`の時に値が`default`になった場合は`null`として扱われないですよね?
Zuishin

2019/03/08 04:58

Nullable は値型にしか使えません。default(int) は 0 ですから、HasValue が true で値(Value)が default というのは 0 になります。
tamoto

2019/03/08 05:00

えっと、Nullable<T>は構造体で、構造体のdefaultを生成するとバイト列が全部0のデータが手に入ります。全部0ということはHasValueも0(==false)で、これをnullを生成したものとして扱うのがNull許容です。
Zuishin

2019/03/08 05:04

いやさすがに全バイト見てないと思いますよ。 Nullable<T> の T 型が大きなデータ型ということもありえますから。
Takym

2019/03/08 05:07

Zuishinさん、tamotoさん、 ありがとうございます。
tamoto

2019/03/08 05:07

あ、そうですね、nullとの比較ではHasValueしか見てないはずでした。
guest

0

気になるなら、計測しなよ。
せいぜい、これからは気をつける、速度が絶対必要なら治すぐらいのことかと。

投稿2019/03/08 04:09

kiichi54321

総合スコア1984

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

Program.cs

1using System; 2#nullable enable 3 4var a1 = new A(); 5Console.WriteLine(a1 is null); 6A? a2 = new A(); 7Console.WriteLine(a2 is null); 8Console.WriteLine(a2 == null); 9var b1 = new B(); 10Console.WriteLine(b1 is null); 11Console.WriteLine(b1 == null); 12B? b2 = new B(); 13Console.WriteLine(b2 is null); 14Console.WriteLine(b2 == null); 15C? c = new C(); 16Console.WriteLine(c is null); 17Console.WriteLine(c == null); 18 19class A { 20 public static bool operator ==(A a1,A a2) => false; 21 public static bool operator !=(A a1,A a2) => false; 22} 23class B { 24} 25struct C{ 26}

みたいに書いたとき、

Program.cs

1A a1 = new A(); 2Console.WriteLine((object)a1 == null); 3A a2 = new A(); 4Console.WriteLine((object)a2 == null); 5Console.WriteLine(a2 == null); 6B b1 = new B(); 7Console.WriteLine(b1 == null); 8Console.WriteLine(b1 == null); 9B b2 = new B(); 10Console.WriteLine(b2 == null); 11Console.WriteLine(b2 == null); 12Nullable<C> c = default(C); 13Console.WriteLine(!c.HasValue); 14Console.WriteLine(!c.HasValue);

の様に解釈されている為、 比較対象のクラス・構造体がどういうものが意識したくないのであれば
is null を使った方がいいのではないでしょうか?

実際のソース

投稿2020/12/18 00:44

juner

総合スコア110

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問