🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
.NET Framework

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

VB.NET

Microsoft Visual Basic .NETのことで、Microsoft Visual Basic(VB6)の後継。 .NET環境向けのプログラムを開発することができます。 現在のVB.NETでは、.NET Frameworkを利用して開発を行うことが可能です。

Q&A

解決済

4回答

4627閲覧

If文とIf演算子の挙動が違う理由

heart_crimson

総合スコア15

.NET Framework

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

VB.NET

Microsoft Visual Basic .NETのことで、Microsoft Visual Basic(VB6)の後継。 .NET環境向けのプログラムを開発することができます。 現在のVB.NETでは、.NET Frameworkを利用して開発を行うことが可能です。

0グッド

2クリップ

投稿2019/10/15 07:46

言語はVB.NET、環境は.NET Framework 4.5です。
If文とIf演算子の挙動が違う理由、具体的には「下記コードのbとdが同じ結果にならない理由」を知りたいです。
参考になるサイト等があればご教授いただけますと幸いです。
(これで不具合を作ってしまい時間をロスしてしまったので、戒めとしてきちんと知識をつけておきたいのが質問した理由です。)

以下、テストコードです。

VB

1Sub Main() 2 Dim a As Date? 3 Dim b As Date? 4 Dim c As Date? 5 Dim d As Date? 6 7 a = If(True, Date.Now, Nothing) 8 9 b = If(False, Date.Now, Nothing) 10 11 If True Then 12 c = Date.Now 13 Else 14 c = Nothing 15 End If 16 17 If False Then 18 d = Date.Now 19 Else 20 d = Nothing 21 End If 22 23 Console.WriteLine(a) 24 Console.WriteLine(b) 25 Console.WriteLine(c) 26 Console.WriteLine(d) 27 Console.ReadKey() 28 29End Sub 30

Console

12019/10/15 16:19:42 20001/01/01 00:00:00 ←何故Nothingではなく既定値になっている? 32019/10/15 16:19:42 4(ここに1行空白がある)

以上、よろしくお願いいたします。

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

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

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

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

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

guest

回答4

0

ベストアンサー

これは型推論のせいです。次のようにすると同じ結果になります。

VB.NET

1b = If(False, CType(Date.Now, Date?), Nothing)

元の記述の場合

VB.NET

1b = If(False, Date.Now, Nothing)

Date.Now が Date? 型ではなく Date 型なので、Nothing は Date 型と推論され、その結果 Date 型の規定値になっています。

投稿2019/10/15 08:20

Zuishin

総合スコア28669

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

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

0

こんにちは。

VB.NET は全く触っていないですが、少し奇妙な見た目だったので調べてみました。

今回の問題は If operator の then part と else part が同じ型を持っていなければならないルールによるものです。
If operator の then part に置かれている Date.Now の型は Date? ではなく Date なので、Nothing の方も Date 型として扱われ、即ち default value (01/01/0001 00:00:00) となっています。
If operator 全体の型は Date となっていて、それを最後に Date? 型の変数に代入するという動作になっています。
If statement の方ではそれぞれのブロックで値を Date? 型の変数に代入しているため、Nothing が正しく Date? 型として扱われているため、意図した動作になっています。

投稿2019/10/15 08:20

tamoto

総合スコア4250

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

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

0

みなさま、ご回答ありがとうございました。

  • If演算子はTrue時の処理とFalse時の処理の型を合わせに行く(型推論)
  • Date.Now()がDate型なので、NothingもDate型とみなす
  • 変数がNothing非許容の場合、Nohtingを代入したり初期値を入れないままインスタンスを作成すると既定値になる

以上のため、質問文のような挙動になることが分かりました。
VBはNothing非許容の型にNothingを入れると既定値になってしまうの、罠な気がしました…。普通にNothing入れてほしかっただけなのですが…。

ちなみに「If(True, Nothing, Date.Now())」にしても既定値になりました。

VBの仕様まで深く理解でき、自分の知識としてちゃんと定着したように思えたため、解決とさせていただきます。
改めて、この度はありがとうございました。

投稿2019/10/17 00:43

heart_crimson

総合スコア15

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

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

Zuishin

2019/10/17 00:43

既存の回答による解決です。ベストアンサーを選んでください。
heart_crimson

2019/10/17 00:58 編集

すみません、みなさまの意見をまとめようということで投稿したのですが、自分の回答がベストアンサーになるとは想定していませんでした…。 ベストアンサーの変更って出来ませんかね…? 追記 変更できました。薄い灰色だったので目立たなかった…。失礼いたしました。自分が悪いのは分かっていますけどすごい勢いでマイナス評価されていくの少しへこみますね…。 再追記 マイナス消していただきありがとうございます。ちょっとびっくりして挙動不審になってしまいました。
Zuishin

2019/10/17 00:49

できます。ベストアンサーを解除するだったかそのようなボタンがあるはずです。
guest

0

本家サイトにも記載がありますが、
引数3(Nothing)は、評価されております。

そのため、評価された値の引数3の値が戻ります。

1:IF演算子
2回目は、IF(Boolean型, Date型, Nothing);
この関数では、渡された第二引数と第三引数は型を合わせます。(これが評価です。)
関数の実行内部で型変換により、NothingをDate型のNothing(Date型の規定値として)返します。

2:IF制御構文
Nothing(null)を代入しています。
※変数dはnull許容型なので、Nothing(null)が代入されています。

今回、ご質問の件ですが、
つまるところ、型の一致をさせる処理が動くため、演算子と制御構文で違いがあるです。
同じ挙動にする場合、IF演算子で行う処理とIF制御構文で行う処理を厳密に合わせる必要が発生します。

下記に参考リンクを挙げておりますが、
何故か?の理由は、ショートサーキット評価を行う際に、型を一致させるためです。

日本語が変で申し訳ありません。

【追記】
何故この様な型キャストが起きるのか?
こちらについては、このIF演算子の使い方が答えとなります。
この演算子は、厳密なOR代入です。
第一引数を評価して、真なら第二引数を、偽なら第三引数を、
それぞれ評価してから、推論の型で返却し左辺(変数)へ代入します。
代入する値の型が変数の許容外の場合、型の不一致エラーが起こりますので、
それを起こさない為に渡された引数の型から返すべき値の型を推論します。

※ショートサーキット評価の場合、疎漏なOR代入の為に実行時点で、
例外スローか発生しますので、下記の参考リンクの様にエラー文が有ります。

本家リファレンス
参考リンク

投稿2019/10/15 07:59

編集2019/10/15 14:41
tama_yn0815

総合スコア143

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

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

Zuishin

2019/10/15 08:10

Date? なので null 許容型ではありませんか? また Nothing は null 非許容型の変数に代入すると規定値になるはずです。
tama_yn0815

2019/10/15 08:16

そうですよね。。。ちょっと、回答を修正しています。
Zuishin

2019/10/15 15:25 編集

厳密な OR 代入、疎漏な OR 代入という言葉は初めて目にしました。OR 代入演算子というのは知っていますが、それらは調べてもわかりませんでした。 評価に関してですが、型を合わせることではなく、値を確定することを評価と呼びます。if 演算子の場合、第一引数が true であれば第二引数は評価されますが、第三引数は評価されません。逆に第一引数が false であれば第二引数は評価されません。 また、この結果によって実行時にエラーが起こったのではなく、リンク先では逆に「評価されない証拠として、評価された際にはスローされるはずの 0 除算エラーがスローされないこと」を示しています。 このドキュメントで 0 除算エラーが発生すると言われているのは、if 演算子ではなく iif 演算子です。iif 演算子は第一引数の値に関わらず、第二引数と第三引数の両方を評価するため、このようなことになります。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問