投稿者 魔界の仮面弁士  (社会人) 投稿日時 2023/1/19 09:40:39
=====
(4) コンパイル時の各種警告について
-----
警告 BC42105: 関数 'SelectLanguageChrSet' は値を返さないコード パスがあります。結果が使用されるときに、null 参照の例外が実行時に発生する可能性があります。
→列挙型には、CType(100, Language) などどして、未知の値をセットすることもできるため、
 コンパイラ的には、これでは条件分岐が不十分と判断されます。
 万一、未知の値が渡されてしまった場合の振る舞いも定義しておきましょう。
 (案1) 何らかの例外を投げる
  Throw New ArgumentOutOfRangeException(NameOf(language), language, "不明な Language です")
 (案2) 不明な言語は、既知の言語のいずれかと同一視させる(たとえばFrench扱い)
 (案3) Return Nothing とする
 (案4) Return New Dictionary(Of Char, Char)()


警告 BC42104: 変数 'seqStr' は、値が割り当てられる前に使用されています。Null 参照の例外が実行時に発生する可能性があります。
警告 BC42104: 変数 'word' は、値が割り当てられる前に使用されています。Null 参照の例外が実行時に発生する可能性があります。
警告 BC42104: 変数 'lst' は、値が割り当てられる前に使用されています。Null 参照の例外が実行時に発生する可能性があります。
→seqStr は いずれの If 条件にも一致しなかった場合、
 word と lst は、いずれの Case 条件にも一致しなかった場合が考慮されていません。
 Else 条件を追加するか、あるいは変数宣言時に初期値をセットするようにしましょう。
 もしも初期値は設定したくないが、状況的に絶対に Else 句に来るはずもない、という場合は、
 Else 句にて例外を Throw する実装にしておくという手もあります。
 (たとえば InvalidOperationException、NotImplementedException、ArgumentException など)
※sequalNumStr デリゲートという名前もちょっとよく分からず。sequal とは何を意味しますか?


警告 BC42353: 関数 'HasDgvError' には値を返さないコード パスがあります。'Return' ステートメントが不足していないかどうかを確認してください。
→戻り値が As Boolean なのに、Return True が For ループの中にしかありません。
 列数が 0 だった場合、ループ内の Return が呼ばれないので注意されています。
 エラーではなく警告なのは、Boolean 型の既定値は False であるためですが、
 このケースでは、Next と End Function の間に「Return False」を設けるべきでしょう。


警告 BC42105: 関数 'GetRegularPlural' は値を返さないコード パスがあります。結果が使用されるときに、null 参照の例外が実行時に発生する可能性があります。
→ Function の中身が空です。オーバーライド先で困ってしまうので、
 戻り値をきちんと返すようにしましょう。あるいは MustInherit クラスで
 振る舞いを定める予定がない場合は、"Overridable" ではなく "MustOverride" を用います。
 動作を実装したくないという場合は、"Throw New NotImplementedException()" を記述しておくのも良いでしょう。


警告 BC42025: 共有メンバー、定数メンバー、列挙型メンバー、または入れ子にされた型にインスタンス経由でアクセスしています。正規の式は評価されません。
→ これは多数出ていますが、たとえば PopUpBase クラスを見てみます。この場合、
 「ElseIf e.KeyData = Keys.KeyCode.Escape Then」というコードが不自然です。
 左辺の e.KeyData の戻り値は System.Windows.Forms.Keys 列挙型を示していますので、
 右辺は System.Windows.Forms.Keys.Escape もしくは単に Keys.Escape とします。
 この警告を別の例で置き換えてみると、たとえば
  Dim w = DayOfWeek.Tuesday
 と書くべき箇所で
  Dim w = DayOfWeek.Sunday.Monday.Tuesday
 と書いていた場合に発生するものと同じである…と書けば、その不自然さが伝わるでしょうか。

 また、Keys.KeyCode という値は e.KeyData に対するビットマスクとして
 用いられるものであり、それ単体で比較されるような値でありません。
 Dim a As Keys = e.KeyData And Keys.KeyCode 'この a は e.KeyCode と等しい
 Dim b As Keys = e.KeyData And Keys.Modifiers 'この b は e.Modifiers と等しい
 Dim m1 As Boolean = e.Modifiers.HasFlag(Keys.Alt) 'この m1 は e.Alt と等しい
 Dim m2 As Boolean = e.Modifiers.HasFlag(Keys.Control) 'この m2 は e.Control と等しい
 Dim m3 As Boolean = e.Modifiers.HasFlag(Keys.ShiftKey) 'この m3 は e.Shift と等しい

 その直前にある
 「If e.KeyCode = Keys.KeyCode.Alt And e.KeyData = Keys.KeyCode.Enter Then」
 も同様の誤りを含んでいますが、こちらはそれに加えて、
 e.KeyData と e.KeyCode の混在利用という点も不自然です。
 (KeyData と KeyCode の違いは分かりますか?)
 それに論理演算ならば AndAlso/OrElse を使うべきです。
 ビット演算なら And/Or でも構いませんが、上記は論理演算のはずですよね。