C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[13]: bool変数の比較演算について


(過去ログ 147 を表示中)

[トピック内 24 記事 (1 - 20 表示)]  << 0 | 1 >>

■86166 / inTopicNo.1)  bool変数の比較演算について
  
□投稿者/ ヒークン (1回)-(2017/12/22(Fri) 12:31:08)

分類:[VB.NET/VB2005 以降] 

色々なサイトのVBのサンプルコードを見ると、

If (bool変数) = True Then
If (bool変数) = False Then

のように、bool変数を=で比較するような書き方を見ることがあります。

ただ、普通は、

If (bool変数) Then
If Not (bool変数) Then

のように書くのではないかと思いますが、
bool変数を=で比較することに何か理由があるのでしょうか?
(例えば、何らかの理由で、昔はそのように書いていた、等)
引用返信 編集キー/
■86170 / inTopicNo.2)  Re[1]: bool変数の比較演算について
□投稿者/ ぶなっぷ (156回)-(2017/12/22(Fri) 13:06:19)
結論から言うと、どっちでもいいです。

たとえば、以下のようにすると、
    Dim a As Integer
    a = 10
    Console.WriteLine(a > 0)
    Console.WriteLine(a < 0)
True
False
と表示されます。分かりますか?
実は、比較演算子の結果というのはbool型なんです。

なので、
    Dim b As Boolean
    b = True
としたとき、
    If (b = True) 
    If (b = False) 
と、
    If (b)
    If (Not b)
は、全く同じ意味です。

引用返信 編集キー/
■86171 / inTopicNo.3)  Re[1]: bool変数の比較演算について
□投稿者/ WebSurfer (1404回)-(2017/12/22(Fri) 13:07:28)
No86166 (ヒークン さん) に返信

単なる個人的意見ですが、昔からの流れのようなものがあるのではないでしょうか?

VB は知りませんが C の場合、例えば、

if (expression) statement

で expression は算術型かポインタ型でなければなりません。expression が評価され、結果が 0 で
なければ statement が実行されます。

なので、

if (!valid)



if (valid == 0)

は同じです。どちらの形式がより良いかは一般的には言えません。上記の !valid の例ならともかく、
もっと複雑な構文になると理解しにくくなるので、valid == 0 のようにした方が良いかもしれません。

C# で if (valid == ture)、VB.NET で If valid = True と書くのもその流れからきているのではな
いかと思います。

他には、好みの問題とか、組織のコーディングルールなどもあると思います。
引用返信 編集キー/
■86172 / inTopicNo.4)  Re[2]: bool変数の比較演算について
□投稿者/ ヒークン (2回)-(2017/12/22(Fri) 13:28:20)
皆さん、コメントありがとうございます。

> 実は、比較演算子の結果というのはbool型なんです。

もちろん、これは理解の上での質問なのですが、
「If (bool変数) = True Then」は、
「If (bool変数) Then」に比べて
「(bool変数) = True」という比較演算を余計にしているのではないか
(無駄な演算をしているのではないか)という疑問から、
この質問をさせて頂いた次第です。

また、
「If (bool変数) = False Then」も、
「(bool変数) = False」と「Not (bool変数)」で
演算コストは同じなのかな、という疑問を持ちました。

ブール代数的な考えでは、「(bool変数) = True」のような比較演算は
やっぱり違和感がありますが、気にしすぎなのでしょうか?
引用返信 編集キー/
■86173 / inTopicNo.5)  Re[2]: bool変数の比較演算について
□投稿者/ 774RR (581回)-(2017/12/22(Fri) 13:28:45)
if ((a==true)==true) // C の場合
If ((a=true)=true) // VB の場合
if ((a>b)==true) // ちょっと例として違うかもしれんが
としないのはなぜ? という意見もあるわけで
http://www.kouno.jp/home/c_faq/c9.html

書いた人のポリシーとか、ローカルコーディングルールとかあたりに原因がありそう。

オイラ個人のポリシーでは [ bool 式であることが明確な場合 ] は ==true や ==false は書かない。
Cでポインタ式が NULL かを比較するときは p==NULL ないしは p!=NULL を明示する、かな・・・

引用返信 編集キー/
■86174 / inTopicNo.6)  Re[3]: bool変数の比較演算について
□投稿者/ ヒークン (3回)-(2017/12/22(Fri) 15:07:58)
皆さん、コメントありがとうございます。
なるほど、コーディングルールなどもあるのですね。
また、C言語のお話も興味深かったです。

このスレッドはもう少しこのままにしておきます。
引用返信 編集キー/
■86175 / inTopicNo.7)  Re[4]: bool変数の比較演算について
□投稿者/ ぶなっぷ (157回)-(2017/12/22(Fri) 15:36:08)
無駄な演算してるかどうかですが、コンパイラ次第かと思います。
最近のコンパイラは賢いので、コンパイラの最適化でどっちも同じになるような気がします。
確認したわけではないので、あくまで推測です。

引用返信 編集キー/
■86176 / inTopicNo.8)  Re[4]: bool変数の比較演算について
□投稿者/ 774RR (582回)-(2017/12/22(Fri) 15:38:17)
通常、コンパイラは翻訳時点でわかりきった比較を最適化してしまうので
if (a) も if (a==true) も if ((a==true)==true) も同一のコードを生成するだろう。
というわけで、組織的コーディング規則とかが
・ない場合、自分にわかりやすいコードを書けばよいだろう
・ある場合、それにしたがっておけばよいだろう
ということになる、んぢゃないかな。

if (a==true) に違和感があるという印象はとても素敵だと思う。その感覚を大事にして欲しい。

データベースなんか扱い始めると3値ブールなんてのが出現して気が狂いそうになるっす。
オイラ的にはあまり近づきたくない世界。

引用返信 編集キー/
■86177 / inTopicNo.9)  Re[5]: bool変数の比較演算について
□投稿者/ とっちゃん (481回)-(2017/12/22(Fri) 17:13:43)
最適化などはコンパイル結果を見るのがいいと思いますが、そちらは置いておいて。。。

歴史的経緯と権威のある真偽を表す型も載せておきます(便宜上C形式)。

typedef short VARIANT_BOOL;
#define VARIANT_TRUE ((VARIANT_BOOL)-1)
#define VARIANT_FALSE ((VARIANT_BOOL)0)

typedef int BOOL;
#define FALSE 0
#define TRUE 1

前者は、COM および、VB6までのBoolean型(VBAを含む)。
後者は Windows API におけるBOOL型(CやC++という言語のものではない)

さらにおまけ的な知識としては
BOOLを戻り値の型にしているWindows API のいくつかは失敗した時は 0(==FALSE)、成功は !0(!=TRUE) を返すものがあります。

古い知識(.NET 内で完結してる限り影響しない)ですが、知ってるとちょっとだけいいかもw

引用返信 編集キー/
■86195 / inTopicNo.10)  Re[6]: bool変数の比較演算について
□投稿者/ Jitta (349回)-(2017/12/24(Sun) 11:06:46)
最近のIDEでは書き換えを提案して来たりしますね。
引用返信 編集キー/
■86196 / inTopicNo.11)  Re[7]: bool変数の比較演算について
□投稿者/ ヒークン (4回)-(2017/12/24(Sun) 12:20:07)
2017/12/24(Sun) 12:23:05 編集(投稿者)

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

私はソフト開発会社に勤めているわけではないので、
一般的な開発ルール等は全く存じ上げないため、
おかしな質問があればそれはご容赦頂きたいのですが、
色々とお話しを伺う中で、一つ思ったのは、
場合によっては、否定分岐で「If a = False Then」とした方が安全な
環境があるのではないか、ということです。
この「環境」とは、OSや言語というよりは、開発者サイドの仕様だったり、
開発ルールの環境を指します

そう思った理由の一つとして、
WebSurferさんの■86171の例示

> if (expression) statement

の式では、expression == 0の場合は偽、それ以外は真と評価されます。
C言語のことは良く分かりませんが、VBでNot演算を行うと、
「Not expression」はexpressionのビット反転ですので、
expressionが0以外の場合の「Not expression」は、
すべてのビットに1が立っている場合でないと0にはなりません。

このことに気づいたのが、とっちゃんさんの■86177にあった

> #define VARIANT_TRUE ((VARIANT_BOOL)-1)

です。
「1」ではなく、あえて負号付きの「-1」ということは、
これが1ビットではなく、複数ビットであることが分かります。
VBAのVARIANT変数のサイズは勉強不足で分かりませんが、
仮に1バイトだとすると、-1はすべてのビットに1が立っている
&FF(0xFF)ということでしょうか。

そうなると、通常はあり得ないことかも知れませんが、物理的な可能性として
「0または-1を返すメソッドから、バグや何かの間違いで、
それ以外の値が戻ってくる場合がある」ことは0%とは言えないかも知れません。
(限りなく0%でしょうが。)

そこで、「If a = False Then」という式評価を推奨する環境がある、
ということであれば、一定の理解はできます。

しかしながら、「If a = True Then」はどうも受け付けません。
「頭痛が痛い」と言っているのと同じような気がします。(分かり難いたとえでスミマセン)


> if (a==true) に違和感があるという印象はとても素敵だと思う。その感覚を大事にして欲しい。

権威のある方にお褒め頂くことは、非常にうれしい限りです。
しかしながら、if (a==true)(VBのIf a = True Then)は
先程申し上げた通り、違和感「しかない」です。
引用返信 編集キー/
■86197 / inTopicNo.12)  Re[8]: bool変数の比較演算について
□投稿者/ はるまきとかげ (5回)-(2017/12/24(Sun) 15:45:18)
No86196 (ヒークン さん) に返信

> そこで、「If a = False Then」という式評価を推奨する環境がある、
> ということであれば、一定の理解はできます。
> 
> しかしながら、「If a = True Then」はどうも受け付けません。
> 「頭痛が痛い」と言っているのと同じような気がします。(分かり難いたとえでスミマセン)

暗黙の型変換を使用していて
-1, 0の排中律が保証されないならば

If a = False Then

を認めるのと同じ理由で

If a = True Then

を認めるべきだと思いますよ

たとえば-1でも0でもない1はTrueともFalseとも解釈されますからね
https://paiza.io/projects/gU3upzb2fQCXe6xa7x_USA


If a = True Then
If a = False Then

それはそれとして私はこの書き方は変数の位置が
揃っていてTrue、Falseという値が対称になるので
きれいに思いますし好きですけどね

好みの問題かなと

引用返信 編集キー/
■86201 / inTopicNo.13)  Re[9]: bool変数の比較演算について
□投稿者/ パーティー (1回)-(2017/12/25(Mon) 07:57:28)

> たとえば-1でも0でもない1はTrueともFalseとも解釈されますからね
> https://paiza.io/projects/gU3upzb2fQCXe6xa7x_USA

何か勘違いしていませんか?
質問者はif (expression) のexpressionの内容のことを言っているのであって、
その意味ではそのサイトはexpressionが0でないものがConsole.WriteLineされていますよね。

引用返信 編集キー/
■86202 / inTopicNo.14)  Re[10]: bool変数の比較演算について
□投稿者/ ヒークン (1回)-(2017/12/25(Mon) 10:55:29)
皆さん、コメントありがとうございます。
私の話は、

If (expression) Then で

expression = 0 は偽と評価され、
それ以外の値の場合に真と評価されることを前提としています。

この前提では、仮にaが1という値を持つ場合、
当然、If a ThenとIf a = True Thenは異なる評価となります。
そのような状況では、そもそもIf a = True Thenは危険だと思うのですが、
どうでしょうか?

そうは言っても、今では通常、bool型の変数はTrueとFalseの値しか持たず、
bool変数をTrueやFalseで比較しても、コンパイル時に最適化してくれるため、
コードの可読性のため、(bool変数 = True)のような書き方をルール化している所もある、
というところまでは理解できました。

ただ、私は、If a = True Thenのような表記はまどろっこしく感じるため、
何か他に理由があるのではないか、という思いがあるのです。
その仮定の一つが■86196で述べていることです。

しかし、皆さんのお話を聞いているうちに、
もしかしたら、私のような考え方は少数派なのかな、とも思いました。
引用返信 編集キー/
■86203 / inTopicNo.15)  Re[11]: bool変数の比較演算について
□投稿者/ shu (1074回)-(2017/12/25(Mon) 11:41:49)
No86202 ( ヒークン さん) に返信
> 皆さん、コメントありがとうございます。
> 私の話は、
>
> If (expression) Then で
>
> expression = 0 は偽と評価され、
> それ以外の値の場合に真と評価されることを前提としています。
>
> この前提では、仮にaが1という値を持つ場合、
> 当然、If a ThenとIf a = True Thenは異なる評価となります。
> そのような状況では、そもそもIf a = True Thenは危険だと思うのですが、
> どうでしょうか?
>
内部的に整数で扱っていたとしてもBoolean型として正式に実装されている
言語であれば

内部的にa=1, b=2
であってもBoolean型としてはa = bとならなければなりません。
整数として比較してはダメです。前提がそうなっているのですからそのように比較すべきです。


引用返信 編集キー/
■86204 / inTopicNo.16)  Re[12]: bool変数の比較演算について
□投稿者/ furu (154回)-(2017/12/25(Mon) 13:16:52)
C#(Cも)の否定が1文字の単項演算子なので
見づらく、間違いやすく、プログラムの可読性も
悪いので冗長的に書いてるだけだと思います。

特にサンプルプログラムだと
trueかfalseが重要なので

VBのサンプルコードがそうなのは
C#のサンプルコードと並列して表記するので
同じように書き始めたのではないでしょうか。

if (!!!!!true)
   ↓↓↓
if (true == false == false == false == false == false)
かな
引用返信 編集キー/
■86206 / inTopicNo.17)  Re[8]: bool変数の比較演算について
□投稿者/ 魔界の仮面弁士 (1524回)-(2017/12/25(Mon) 13:46:10)
2017/12/25(Mon) 14:36:56 編集(投稿者)

No86196 (ヒークン さん) に返信
> 「0または-1を返すメソッドから、バグや何かの間違いで、
> それ以外の値が戻ってくる場合がある」ことは0%とは言えないかも知れません。

ヘッダー ファイル WinDef.h においては
 #define FALSE  0
 #define TRUE   1
と定義されていますが、『BOOL を返す大部分の関数はゼロ以外の値を返してブール値の真を示す』ため
TRUE との等価演算を記述するべきではないと、下記に記載されていますね。
https://msdn.microsoft.com/ja-jp/library/windows/desktop/ff381404.aspx

>> // 正しい記述
>> BOOL result = SomeFunctionThatReturnsBoolean();
>> if (result)
>>
>> // 誤った記述
>> if (result == TRUE)
>>

ブール型にまつわる歴史の話をさせてもらうと、
C++ には bool 型がありますが、C にはありません。
そして Visual Basic 2.0 にも、Boolean 型は存在していませんでした。


そして VB2 当時の論理値は、整数として比較されるという言語仕様です。

VB2 時代の組み込みデータ型は、以下の 7 種類だけです。
 Integer
 Long
 Single
 Double
 Currency
 String
 Variant
これに加えて、ユーザー定義型が使えました。
Boolean の他、Byte や Date や Object さえも存在していません。


一方、Variant 型の内部値としては、VarType 関数で見ると 9 種類ありました。
そしてその中にさえ、論理型を表すデータタイプは存在していません。

 0 / V_EMPTY … Empty 値 (ただしまだ Empty キーワードは無い)
 1 / V_NULL … Null 値
 2 / V_INTEGER … True / False もここで扱う
 3 / V_LONG
 4 / V_SINGLE
 5 / V_DOUBLE
 6 / V_CURRENCY
 7 / V_DATE … 日付リテラルや CVDate 関数で生成(CDate 関数はまだ無い)
 8 / V_STRING

ちなみに上記の V_INTEGER や V_EMPTY というのは、今で言う vbInteger や vbEmpty のことです。
当時は組み込みの定数が殆ど用意されておらず、マジックナンバーを直接記述するか、
Constant.txt ファイルにある「Global Const V_INTEGER = 2」などを
自分で取り込む必要がありました。



本題に戻って Boolean についてですが、VB2 当時のドキュメント上においても、
Boolean 型に関する解説は一応存在しています。ただし当時のヘルプファイルでは、
それが Integer 型の項にマッピングされており、True / False については
Integer 型 (-32768〜32767 の範囲) で表すものとされています。True と False の
予約語が Integer の -1 および 0 に等しい定数であることも明記されていますね。


こうした経緯から、VB における Boolean 型(VARIANT_BOOL) は、
内部値が 0 または -1 な 2 バイトの値となっています。
 False = &H0000
 True = &HFFFF

.NET ではこのマーシャリングが、MarshalAs(VariantBool) な属性として受け継がれています。
とはいえ、.NET の Boolean 構造体の内部値は、整数「1」で管理されているのですが。

ちなみに C++ の bool (byte 型)は MarshalAs(U1) な属性を使用し、
API で用いる Win32 BOOL は MarshalAs(Bool) な属性でマーシャリングされます。
既定のマーシャリング動作は MarshalAs(Bool) です。



> VBAのVARIANT変数のサイズは勉強不足で分かりませんが、

Variant のサイズですが、VB2 当時のマニュアルには記載を見つけられませんでした。

ただし、Put # ステートメントの Variant の項にその内部表現の片鱗を見ることができました。
この部分のマニュアル上の表記は、16bit だった当時も 64bit VBA でも変更されていません。
https://msdn.microsoft.com/ja-jp/vba/language-reference-vba/articles/put-statement

※ Variant の内部表現については、 No86196 (masa さん) で始まる
 「2次元配列のメモリ配置」のスレッドでも触れられています。



> 場合によっては、否定分岐で「If a = False Then」とした方が安全な
> 環境があるのではないか、ということです。

専用の型としての Boolean が無いというだけであり、一応、VB2 当時においても、
 If a Then
 If Not a Then
といった記述は可能でした。

というか、
 Dim v As Variant
 v = #01/02/03#
 If Not v Then
さえ可能だったのですけれどね。

しかし、Variant や非数値型以外の指定、具体的には
 strValue = "0"
 If strValue Then
などは実行時エラーではなく文法エラーになる仕様でした。
VB6 では OK です。


しかし当時、
 If a Then
の表記が使われたコードはあまり目にした記憶がありません。

インターネットの使えない当時、私が見ることの出来た他者コードなど、
そこまで多くは無いのですが、それでもあの当時、
 If a = True Then
のような表記ばかりを目にしていたのは、比較対象となるデータ型が
Boolean ではなく、Integer な変数だったというのは、理由の一つでしょう。
(Visible プロパティでさえ Integer 型でした)


とはいえ、当時の VB は、データ型に違いをさほど重要視していなかったので、
これについてはデータ型というより、英文法としての読みやすさとして、
「もし a ならば」よりも「もし a が True ならば」の意図を
優先した結果ではなかろうかと想像しています。
a が Boolean 型だったなら、"a ならば" という表記でもサマになるのですけれどね。


このとき、変数に非 -1 がセットされていた場合に備えて、
 If intValue <> False Then
とするのがより安全だったのかもしれませんが、当時の私は
そのような書き方のサンプルをほとんど見た記憶がありません。
使われていたとしても、 API の呼び出し時ぐらいのもので。

これについては、記号表記の多い C 言語系とは異なり、
BASIC の風潮が英文法表現を是とするものであったため、
「真である」ことを「偽ではない」という表現で書き換えることに
回りくどさを感じていたからではないかな…と思っています。

「While 継続条件」ステートメントの逆となるような
「Until 終了条件」ステートメントをわざわざ用意するぐらいなので、
英文法として読みやすさが、少なからず求められていたのかな、と。


今でも「Not a Is Nothing」→「a IsNot Nothing」(VB2005以降) や
「Not TypeOf a Is Nothing」→「TypeOf a IsNot Nothing」(VB2015以降) のような
表現が追加されたのも、英文法的な読みやすさの向上を目的として
比較演算子が使われていたというのは、理由の一つになりえる気がします。


> しかしながら、「If a = True Then」はどうも受け付けません。

Microsoft のサンプルでも両方の表記がありますし、私としては
どちらでも良いかなと思っています(多数派に合わせる)。

どちらか一方を選べと言われたら、今なら付けない方に合わせるかな…。
ちなみにうちの社内ルールでは等価演算子を付与しないことが推奨されています。



今回の話とは若干外れますが、2値比較ではなく3値比較だった場合は、
下記で 300 が渡されるケースがありえますね。


If boolValue = True Then
 intValue = 100
ElseIf boolValue = False Then
 intValue = 200
Else
 'VB.NET (2005 以降) において、「boolValue が Nullable(Of Boolean) 型の Nothing 値」だった場合や
 'VBA / VB2〜VB6 において、「boolValue が Variant 型の Null 値」だった場合にはここを通る
 intValue = 300
End If


var b = default(bool?); の場合、C# の if (b == b) は真ですが、
Dim b As Boolean? = Nothing の場合、VB の If b = b Then は偽になる…。
引用返信 編集キー/
■86207 / inTopicNo.18)  Re[9]: bool変数の比較演算について
□投稿者/ みい (77回)-(2017/12/25(Mon) 13:56:54)
今就職経験のない新人君に仕事教えていますが
「if (!bXXX)」(bXXX:BOOL)で「何をやっているのか分かりません」
と言われました。


どうやら学校の授業で「真偽」ではなく「==:左辺と右辺の条件成立」
「!=:左辺と右辺の条件不成立」で教えられたもようです。
引用返信 編集キー/
■86208 / inTopicNo.19)  Re[11]: bool変数の比較演算について
□投稿者/ WebSurfer (1411回)-(2017/12/25(Mon) 14:06:08)
No86202 ( ヒークン さん) に返信

> ただ、私は、If a = True Thenのような表記はまどろっこしく感じるため、
> 何か他に理由があるのではないか、という思いがあるのです。

自分の好みの問題で言わせてもらえると、If a = True Then は「もし a が真だったら」
と容易に読めるのでそれなりのメリットがあると思います。

逆に、If a Then は「何これ? a って一体何なの?」という感じがします。

でも、a というような何だか分からない命名ではなくて、例えば IsResultTure ならば、
If IsResultTure Then の方がよさそうで、逆に If IsResultTure =True Then は違和感
たっぷりです。

要は、書いた人も含めて後で保守する人が読みやすく&パッと見ただけで理解しやくすく
するということを考えるのがよさそうな気がします。
引用返信 編集キー/
■86209 / inTopicNo.20)  Re[10]: bool変数の比較演算について
 
□投稿者/ ヒークン (2回)-(2017/12/25(Mon) 15:15:03)
皆さん、コメントありがとうございます。
みなさんのお話を聞いていくうちに、
色々な歴史の上に成り立っているんだなーという感想を受けました。

また、私はこういった類の専門学校のカリキュラムを知りませんが、
そこでは真偽の概念は教えないんですね。
(ド・モルガンの定理とかもやらないのかな?)
引用返信 編集キー/

次の20件>
トピック内ページ移動 / << 0 | 1 >>

管理者用

- Child Tree -