トップページ > Tatsuの開発室 > くたばれVisual Basic(.net) in 2023
くたばれVisual Basic(.net) in 2023
このページは仕事でVisual Basic.netを使っていた時に、あまりの使いにくさにぶち切れてやけくそで書いたページである。
.netになってからのVisual Basicに関しては本当ににくたばれと思っているのでそこんとこよろしく。
結論
まずは結論から言わせてもらう。
新しく使うな!全力で避けろ!C#潜り込ませることができるのであれば可能な限りC#を潜り込ませて乗っ取れ!
新規プロジェクト・初学者
.NETなVisual Basicは劣化C#でしかないので単に字面が違う上にタイプ数が多いC#でしかない上、書ける物もC#より少ないので、選ぶ理由はない。
更に人気面ではPython/Java/C & C++/C#より低く、利用率でもJavaScript/PHPなどより低いので役に立つ可能性は他の言語より低い。もちろん情報量も他の言語よりは少ない。今から始め得るのは時間の無駄である。
経営者・プロジェクトリーダー
.NETなVisual Basicは後述するように生産性を下げる要素てんこ盛りなので他言語の1.5倍の工数・コストを見積もること。
営業
.NETなVisual Basicは後述するように生産性を下げる要素てんこ盛りなうえ、コンバーターの不出来、かつてからのいわゆるVB屋の意識の低さなど魑魅魍魎の嵐なので目先の案件ほしさに選ぶことはおすすめしない。追加コストで売り上げが想定より落ちるリスクが大きい。
現場作業者
全力で逃げろ。営業の項でも話したが、魑魅魍魎の嵐なので思わぬ工数増によるQOLの低下、精神的なダメージを受ける可能性が大きい。
どこがだめか
では、.NETになったVisual Basicはどこがだめでくたばれと思ったかについて書いていく。
言語・ライブラリ基本編
言語としての不出来
劣化C#でしかないという事実
一部の演算子を除くと新たな言語要素は.NET Frameworkの機能に対応する物がほとんどである。
その割にLINQと合わせて使うのに欠かせないラムダ式の2008の頃のとか、C#で何かと便利なnull関連の演算子は取り込まないなど事実上C#の劣化版にしかなっていない。
未初期化のローカル変数のチェックが甘い
未初期化のローカル変数は勝手に0やNothingで初期化されるが、使用開始時のチェックが甘い。
実際に使っている現場ではなまじコンパイルが通るせいで動かすと初期化忘れで例外が出るバグが多い。まさに余計なお世話。
JavaやC#のコンパイラのようにプログラムの流れによって未初期化になるケースの検出が甘い。コンパイラーの手抜きだったとしか言えない。
C++ですら今ではチェックするのだが。
なのに未使用の変数だけはチェックする。なぜ未使用変数チェックだけやって未初期化の変数チェックがないんだか。
戻り値の未設定チェックがない
VBの個性といえば関数名が戻り値の値になるのだが、これに何も入れてなく、Return文も使わないときのチェックもない。
これもまた戻り値設定忘れによるバグの元になる。
Is演算子
参照の比較だけ特別な式にする必要性がわからない。参照代入用のSetステートメントがなくなったのでここで直しておけば良かったのだが。
.NETのライブラリ規約に制限を加えた符号なし型の後付け
ちなみに、符号なし型もなぜか2002になくて2003にはある。Javaは符号なし型なしでずっとやってきているのでそのスタイルなら納得がいくのだが。おかげで>NETライブラリ作成ガイドラインで符号なしは作るなという規約だけが名残として残ってしまった。符号なしの方が楽に書けるところはファイルサイズ計算などが考えられるのだが。
イベントハンドリングの混乱
イベントのハンドリングに、Add HandlerとHandlesがあるが、本家の説明でも混乱しているように混乱している。
更にHandlesを使われるとVisual Studioで参照数が加算されず使用箇所を見逃すという致命的な弱点がある。
Windows Formsデザイナー、XAMLコンパイラーがAdd Handlerを中で使って開発体験をそのままにすると共にAdd Handler文によって参照数を計算できるようにすべきであった。
中途半端な行継続(_省略)
Visual Basicでは伝統的に命令は1行で書く。次の行に続けるときは_を書くというルールがあったが、Visual Basic 2010でそれがなくなった。
のは良いが、他言語と比べるとやけに制限が大きい。コメントや空白などは普通に飛ばせば良いだけなのだが他言語で通っているところがなぜか通らないところが案外ある。そのため、引数が多くならざるを得ないメソッド呼び出しなどを複数行に分けて書きづらいので安心して使えない。
そのため、1行が長くならざるを得なく横スクロールが多くなって見づらくなったり、_をつける昔ながらのスタイルに先祖返りせざるを得なくなったりするなど何かと不便である。
そのため、可読性を取ると_をつける手間が増える、1行書きをすると横スクロールが多くなって見づらくなったり横スクロールの手間がかかると結局コード書きの手間が余り減らないという結果に終わっている。
仕様の検討ミスであったと思われる。
あほなSelect Case文の文法解釈
VBのSelect Case文は複数の値にマッチさせるとき、一つのcaseにカンマ区切りでマッチさせる値を書くという何気に他の言語では見ない個性的な書き方をする。
のは個性としてありなのだが、同じ値が複数のcaseにあると単に無視するだけ。
他の言語だったらエラー出してるぞ。これ。
うっかりやらかしてしまうと意外と苦労する。
逃れられない過去
VB6互換関数
コーディングスタイルの統一がしにくくなるのが困りもの。
コーディング規約を考えるに当たって選択肢が増えるので厄介である。
.NET Frameworkの各型のメソッド使ったほうが書く段階で何が通るか分かるので安全な気がする。
.NETのクラスと混用されてハマりの元になっているのを見るといっそないほうが良かったのではないかという気さえしてくる。
機能的に.NET Frameworkの各型のメソッドより低い物が多いし。
また、ファイル系の昔ながらの#xxを使ったファイルアクセスもメソッド型になっているが、わざわざメソッド型にしなくても良かったのではないかと思った。従来形式なら書き換えなどなしで済むが、メソッド形式になったため学習の手間の割に使う意義が減ったとしか言えない。
ループ系ステートメントの乱立
一番の古株For文に始まり、While...End Whileステートメント、Do...Loopステートメント等似て非なる物がやたらと多くなっていて訳が分からなくなっている。
Until型は他では採用例が少ないので蛇足だと思う。
ループから抜ける文はあるが、かつてループの最初に戻る文はなかった
何気にループ処理の途中で次の要素を処理する際に困った。
2005で各ループにContinue句が付いたのだが、だったら最初からつけておけという感じである。
Withステートメント
オブジェクトの参照を高速化するために使うことが推奨されているけど、ここだけコンパイラの都合を押し付けられる格好になるのはVB.NETらしくないと思う。
省略記法としてうまく使えれば便利なのだが、長いメソッド書くバカに使われると何のオブジェクトのWithか分かりづらく、ソースをおうのに時間がかかるという手間がかかる。
条件判断演算子
And,Or等の条件判断に使われる演算子は一般の演算を兼ねているため、意図が条件判断でも結合するすべての式を評価してから、評価せざるを得ないのでnullチェック等に使うと事故を誘発することが多いのがやっかい。
.NETでAndAlso,OrElseといった条件判定用の演算子ができたが、.NET以前にもVisual Basicになってオブジェクトを使う言語になった時点で条件成立・不成立が確定したら式評価を打ち切るニーズがあったと思われるものであり遅きに失した感がある。
IIF演算子
いわゆる三項演算子でif文の一行版だがなぜか両条件を評価してから判定を行うという使用のため条件不成立時の不正処理を避けるという用途に使えない。And,Or等の演算子と違って数値演算ではなく条件判定なので全くもって馬鹿な仕様である。
C#との機能差が開いた悲しみの2008でようやくまともな条件の成立・不成立で評価の有無を変えるif演算子ができたが、最初からそうしておけという物であった。
地獄の鎮魂歌Option Strict off/VB6コンバート編
意味をなさない型
Option Strict Offの場合、VB6/VBAからExcelを操作するように(というか多くはそのために?)型チェックの解決を実行時に行うレイトバインディングという機能がある。
全クラスの基底であるObject型に対して、それの子クラスとしてCom_Object型があり、COMのオブジェクトをObject型に入れて、これを実行時に解決する。これは分かる。
ただし、COM IeterOPによってすでに型が付いて、その型を使った変数を使った場合はすでに型の解決が行われているので型の解決を行う必要はない。にもかかわらず関数呼び出しで全く違う型の引数として渡したときもコンパイラはそれをエラーとしない。これでは動的型付け言語の型ヒントにも劣る機械的に自動で正確に行えることを人に押しつける実に愚かな行為である。
更にこの挙動、.NETのライブラリにも適用されるのでいよいよもって型の意味がなくなるという物である。
手抜きコンバータ
Visual Studio 2008まではVB6からのコンバーターがあったのだが、手抜きが随所に見られる。
VB6のComboBox/ListBox/CheckedListBoxは選択肢に対応する整数データを持てるが、.NETのWin32コントロールになったComboBox/ListBox、Win32コントロールにないCheckedListBoxについてはコンバータ用メソッドを使う限りは同じように動作するべきであるが、実際には.frmファイルに存在するデータの設定がないのでそれをVB6から転写しないと動作しない。見るとfrmファイルにfrxファイル上のデータのアドレスがあるのでそれを見て、.Designer.vbファイルに転記すれば良かったので手抜きとしか言えない。バイナリ読める人なら誰でもできるぞ。しかもこのデータ設定機構、CheckedListBoxでは動作しないのでテストの手抜きでもある。
他、フォームの挙動違いについての警告漏れ、プロジェクトで参照して型が分かっているはずのCOMの型を一律にObject型に変換する等随所に手抜きが見られる。
不完全なレイトバインディング
DAOのRecordSetをObject型に入れているとCloseメソッドを呼び出すと型を明示したときは問題ない動作がエラーになる等挙動が怪しい場合がある。
似て非なるVB6関数とVB.NETのVBスタイル関数
Format文の書式が一番顕著だが、VB6関数とVB.NETのVBスタイル関数で同じ名前の関数名が二重にあるという事態が起こっており、何らかの事故でVB6.が消えてしまうと字面は合ってそうだけどなぜか動かないという例が頻発する。名前がかぶる関数については名前空間VB6による区別の他に関数名の頭にVB6をつけるなど関数名も変えるべきだったと考える。どうせコンバーターしか使わないんだし。
忌まわしく悪しき最悪の変更 Visual Basic 2005
フォームのデフォルトインスタンス化とインスタンス管理の相違
どこで定義されたかわかりにくく、勝手にインスタンスが生成されたりしてわかり辛い。VB6由来なのだが、便利と思っているつもりだろうがこんなもんは正直言っていらない。せっかく予期せぬインスタンス生成がなくなってフォームインスタンスのコントロールがしやすくなったのに。予期せぬインスタンスの生成はバグの元である。
このへんの画面管理のフレームワークは各オープンソースプロジェクトなどがそれぞれ知恵を絞ってやるべきだと思っているのだが、MSがアプリケーションフレームワークという形でこのVB6への欠点も含めた先祖返りを正当化したうえ、カチカチに組み込んでしまった。これで知恵を絞ったオープンソース当外部サードパーティーの入る余地はできなくなってしまった。
しかも、フォームについては2005で追加されたMyの一環でアプリケーションフレームワークなしでも勝手にインスタンスが作られるようになった上、アプリケーションフレームワークなしの場合、VB6の感覚でウインドウをとりあえず表示すればずっと表示されると思い込んで実際はすぐに閉じるという事故の元となっている。おかげで、その辺の挙動を代行するライブラリを作る羽目になった。極めて迷惑である。
やっかいなのは、ウインドウの開閉状態とウインドウのインスタンス・アプリケーションの生存サイクルが異なることである。そのため、VB6の動作にあわせるにはメッセージループを意識しなくて良かったVB6とは違ってメッセージループを意識した追加のコーディングが必要であり手間が増えている上、VB6とのすりあわせという意図にそぐわない物になっていた。
メッセージループに入った後に書いたメソッドはメッセージループを抜けてからでしか実行されないので初期化漏れなどのバグの元になる、元のVB6ではウインドウが開いていればプログラムが続いていたが、アプリケーションフレームワークにはその辺の配慮がないのでウインドウが開いていても処理をすべて抜けるとプログラム終了、ShowDialogメソッドはVB6では呼び出すとウインドウ生成、閉じたら破棄、再度呼び出したらウインドウ再生成だったのが2005ではダイアログ内容がそのまま残り、動作を合わせるには明示的にDisposeする必要がある等動作が違う点が多く、VB6、2002/2003、2005以降とすべてが違うという混乱状態となった上、手間が余り減ってないという余り褒められる変更とはいえない。
デバッグコンティニュー
デバッグのときしか使えないし、とりあえず動けばよいということで動かした後、整合性がなくなったりどこを直したのか解りにくくなりそうである。いらない。
雀の涙のリファクタリング支援
人がソースを直すよりメソッド名の付け替えやプロパティの生成(面倒!)などがやりやすい上に、正確である。せっかく決まった作業を正確にこなすコンピュータなのだから、これは欲しい。デバッグコンティニューなんかより、こっちのほうが早く欲しかった。しかもこの時点では名前変更とかごくわずか程度のC#と比べると余りにも貧弱な内容。
コンパイラーの再設計でようやくリファクタリングがついたがその頃にはVB.NETは落ち目となっていたので時すでに遅しである。
Myクラス
よく使う(と製作側は思っているんだろうけど実際はどうだか)要素にアクセスするためのクラス。
まったく異なる要素がまとめられているため、ぱっと見で何をしているかが字面から読めず、可読性を損なう。
Tipsの記事がMyクラスを使ったものと他言語でも使えるクラスを使ったものに分散されるため、使い回しが効かない上、検索でC#で何かを行う方法を調べるときに.NETくくりででてくることがあり、C#ユーザーの調べる時間を無駄にしているという意味でC#ユーザーにも迷惑をかけている。
また、これも中途半端に使われるとソース中の統一性が損なわれてソースを読むのに時間がかかるせいで、チームで開発しているときにソース解析の工数や障害対応の工数、開発規約で検討する項目とその議論にかかる時間が増える可能性がある。これ以上無駄な労力を使わせるな。
はっきり言って、VB2005でのライブラリ追加は不具合の作り込みや。生産効率の低下を招く要因となり得る追加が多く、自分としては最悪の追加と考えている。
何をいまさら
未初期化のローカル変数の使用に対する警告やcontinue文なんて新機能として大々的に謳うものじゃないだろう。
と思って2022久々に使ってたら未初期化のローカル変数の使用に対する警告なくなったような気がする。
諸悪の根源、語る。
統合環境
手抜き
バッチビルドが使えない
試験用のデバッグ版とリリース版がいっぺんに作れないので区切りとなるビルドのときにいちいち切り替えるのは面倒だ。
Visual C#やC++でできていることをわざわざできなくする意図が分からない。
Visual Studio 2022になってもいまだに使えないというのはやっぱり謎である。
更に、デバッグ版とリリース版、ターゲットCPUの切り替えがえらく遅い。リリース版はリリース時しか使わないのでバッチビルドが使えないのは本当に痛いという物である。
MSBuild使えば良いのだろうが、他の言語で使えるのが使えないのはいらつくよな。
1つのファイルを2つ以上のタブで開けなかった
移動するのが面倒なくらい離れているところを相互に参照してコーディングを行う時に不便である。
Visual C#やC++でできていることをわざわざできなくする意図が分からない。
これはさすがにVisual Studio 2013ではできるようになっていた。
コード定義ウインドウが使えない
人のプログラムを読んだり、変数・メソッドの定義を知るのに便利なコード定義ウインドウもC#では使えるのにVB.NETでは使えない時がある。
Visual C#やC++ではできているうえ、Visual Studio 2022になってもいまだに使えないというのはやる気を疑う。
使えないWith文内変数表示
With文の中の.から始まる変数にマウスカーソルを当てても変数の値が出ないとか、.の先から変数を選択してマウスカーソルを当てても変数の値が出ないとか、クイックウォッチで表示できないとか、連携するコンパイラコンポーネントなどは知ってるのに何やってるんだか。
そんなWith文、かつては参照の解決の関係で速度が速いということだったけど今はどうなんだか。長いWith文の中のメンバーだけ出されるとほんと見づらいんだよなぁ。
On Error Gotoで呼び出し履歴が出ない
.NETの例外を処理するのにTry文とOn Error Goto文があるが、On Error Goto文で例外処理を行うと呼び出し履歴に呼び出し履歴が出ない。
On Error Goto文もTry文も例外が発生したときのジャンプで例外情報があるのでOn Error Goto文でも呼び出し履歴を出せそうな物だが。
なんで名前空間つけてくれないの?
プロジェクトの下にフォルダを作成してクラスやモジュールを作ってもフォルダ名に対応した名前空間をつけてくれない。
Visual C#ではつけてくれるのに。うーん、めんどい。
アホ挙動
インデントの意味を成さないオートインデント
人がコードに合わせてインデントした左にオートインデントすることがかつてあった。読みにくくなるではないか。というか何のためのインデントか分かってるのか。バカかあほかと
コントロールを継承したコントロールを使うと突然消されることがあった
統合環境のバグ。人が苦労して置いたの勝手に消すなや、ボケ。すぐに統合環境終了させればよいけど誤って保存したらどうする。
Visual C#ではこのバグは存在しない。わざわざバグを作りこんでどうする。
画面分割をするとコードブロックが勝手に畳まれる事があった
開きなおすのがかったるい。
Visual C#やC++ではやってないことをわざわざやって使いづらくする意図が分からない。
.vbproj.user
2008までのプロジェクトのユーザー設定用ファイルにはプロジェクトのフルパスが入っていた。
このせいでDLLを参照したプロジェクトをコピーして使ってもコピー元で参照していたDLLが参照され続けることになり、バージョン管理のときに戸惑う。
Visual C#やC++ではやってないことをわざわざやって使いづらくする意図が分からない。
プロジェクトを作ったばかりの時は実行ファイルの出力先ディレクトリがデバッグ版とリリース版で分かれていなかった。
2008あたりの頃までの話だが、構成を変えたときにコンパイルしなおしになるのは、時間が惜しい。さいしょに
手で変えればよいけど、最初から作ってあったほうが面倒がなくて良いと思う。
Visual C#やC++と初期設定を変える意図がよく分からない。
ちなみに、移行プロジェクトなどでx86固定にせざるを得ないときは初期状態がAnyCPUなので結局そこで作ることになる。
プローシジャ/メソッドの参照カウント
2010年代に入りC#とVBにプローシジャ/メソッドの参照数を表示する機能が付いたが、VB.NETの参照カウント、なんとプローシジャ名だったら何でもカウントするので値を返すためのプローシジャ名が付いた変数へのアクセスまでカウントしてしまう。
複数のところでプローシジャ名が付いた変数に値路入れてアーリーリターンされた日には、もはや何のカウントなんだか分からない。何のための参照カウントなんだか。
ほんの少しの良心
Option Strict On時の縮小変換の既定でのエラー扱い
これをつけないと生産効率的にてんで話になんねえぜな.NETなVisual Basicではあるが、Option Strict On時は縮小変換を既定でエラー扱いにしてくれるのである意味縮小変換によるトラブルが回避できるという意味ではわざとやりたいときもあるだろうが個性というか親切とえるかもしれない。他に褒めるところがないのだが。
その他
Visual Basicという名前そのもの
行番号付の頃のBASICとはどう考えても別物なうえ、かんたんでもなんでもないので多くの人の誤解を招いていると言える。
どれだけの人がだまされたことか。
Basicに似ているけど違うという意味でB#あたりが一番適切か。同時代にMSはJavaの.NET版、J#なんてのも作っていたし関数型言語F#もある。ほげシャープMSが占領しまくったらウケるのだが。
開発環境の代わりがない
CとかJavaとかだと処理系や統合環境に選択肢があるし、C#ではVisual Studio Codeもサポートが厚いがVisual Basic.netには代わりがない。
ディレクトリ構成表示やGitでのソース管理はやってくれるけど、メソッド解析してくれないVisual Studio Codeとその逆のサクラエディタなどの一線級のプレーンなエディタで一長一短になるというのが実に悲しいところである。
だもんで、嫌でもどこか間抜けなVisual Basic.netの統合環境を使わざるを得ないのは苦しいところである。
使い道が分からない
VB6とかVBAと比べると明らかに手軽ではないし、かといって大きいものを組むには混乱を招く仕様が多いため逆に生産性が下がっている。
結局、どこに使うとおいしいのかよく分からない。
BASICって何だっけ?
Microsoft Small Basic なんてものがある(日本語の最後がないのが残念だ)。
.net framework上で動くBasic言語なのだが、こういうものが存在するくらいなので、もはや初心者向けとは言えなくなっている。仕事で使うには今まで述べてきたように問題だらけだし、いったい誰向けの言語なんだろう?
絶望
MicrosoftはVisual Basicについては.NETの機能にアクセスする以外の言語の変更を行わないと表明したので、これらのくそ仕様はもはや変更されないということとなった。救いの可能性はなくなった。
結論
簡単に使えるようにするつもりが無駄な書き方の増加による混乱を招いているケースが多い。そのため、しなくても良い苦労をさせられることが多く、生産性を下げていると思う。
異常進化の袋小路。さっさと絶滅して欲しいものである。
お仲間?
なぜVBはC#と比べて駄目なのか (負け犬プログラマーの歩み)
おまけ
VB.NET用キーワードファイル詰め合わせ
仕事等でVB.netを使わざるを得ない 人向け。とりあえず間抜けな統合環境とテキストエディタを併用するために個人的に作った設定ファイルを集めてみる。
秀丸の強調表示ファイルとK2EditorのキーワードファイルとGreenpadのキーワードファイルの詰め合わせ。