私は基本的にC#の人ですが、最近はVB.Netコードを書いています。
今日、私は.Netの非常に異なる動作に遭遇しました
C#コード
enum Color
{
Red,
Green,
Blue
}
class Demo
{
public static void Main()
{
System.Console.WriteLine(Color.Red);
}
}
このプリント Red
ただし、このコードをVB.Netで記述すると、が出力され0
ます。
VB.Netコード
Module Module1
Sub Main()
System.Console.WriteLine(Color.Red)
End Sub
End Module
Enum Color
Red
Green
Blue
End Enum
なぜそんなに違うの?
C#とVB.NETには、異なるメソッドオーバーロード解決ルールがあります。
C#Console.WriteLine(Object)
はを選択し、VB.NETはを選択しConsole.WriteLine(Int32)
ます。なぜそうなるのか見てみましょう。
アクセシビリティ。呼び出し元のコードがそれを呼び出さないようにするアクセスレベルでの過負荷を排除します。
パラメータの数。呼び出しで提供されるものとは異なる数のパラメーターを定義する過負荷を排除します。
パラメータデータ型。コンパイラは、拡張メソッドよりもインスタンスメソッドを優先します。プロシージャ呼び出しに一致するために拡張変換のみを必要とするインスタンスメソッドが見つかった場合、すべての拡張メソッドが削除され、コンパイラはインスタンスメソッド候補のみを続行します。そのようなインスタンスメソッドが見つからない場合は、インスタンスメソッドと拡張メソッドの両方で続行されます。
このステップでは、呼び出し元の引数のデータ型をオーバーロードで定義されたパラメータータイプに変換できないオーバーロードを排除します。コンバージョンの絞り込み。これにより、呼び出し元の引数タイプから定義済みのパラメータータイプへの変換を絞り込む必要があるオーバーロードが排除されます。これは、型チェックスイッチ(Option Strict Statement)がオンかオフかに関係なく当てはまります。
最小の拡大。コンパイラーは、残りのオーバーロードをペアで考慮します。ペアごとに、定義されたパラメーターのデータ型を比較します。一方のオーバーロードの型がすべてもう一方の対応する型に広がる場合、コンパイラーは後者を排除します。つまり、最小限の拡張を必要とする過負荷を保持します。
単一の候補者。オーバーロードが1つだけ残るまで、ペアでオーバーロードを検討し続け、そのオーバーロードへの呼び出しを解決します。コンパイラがオーバーロードを単一の候補に減らすことができない場合、エラーが生成されます。
には多くのオーバーロードがありWriteLine
、そのうちのいくつかはステップ3で破棄されます。基本的に次の可能性が残されています:Object
および数値タイプ。
5番目のポイントはここで興味深いです:最小の拡大。では、拡大ルールは何と言っていますか?
列挙型(
Enum
)は、基になる整数型と、基になる型が広がる型に広がります。どんなタイプも
Object
したがって、Color
列挙型は最初にInt32
(その基になるデータ型)に広がります-これはConsole.WriteLine(Int32)
。と100%一致します。からに移行するには、さらに別の拡大変換が必要になりますが、上記のルールでは、最小限の拡大を必要とする過負荷を保持するように指示されInt32
てObject
います。
C#について(§7.5.3.2のC#5仕様から):
引数式のセットで引数リストのAを考える
{ E1, E2, ..., EN }
と2人の該当する関数メンバーMP
とMQ
パラメータの型を持つ{ P1, P2, ..., PN }
と{ Q1, Q2, ..., QN }
、MP
より優れた機能のメンバーであると定義されているMQ
場合
- 各引数のために、からの暗黙的な変換
EX
にはQX
、より良いから暗黙の型変換以下ではないEX
とPX
し、- 少なくとも1つの引数については、から
EX
へPX
の変換はからEX
への変換よりも優れていQX
ます。
では、どのように定義するのがよいでしょうか(§7.5.3.4)?
変換指定された
C1
型から変換するS
タイプにT1
、変換C2
タイプから変換するS
タイプにはT2
、C1
より良好変換であるC2
:以下のうちの少なくとも一方が成立する場合
- 恒等変換が存在しているから
S
にT1
ではなく、からS
へT2
T1
T2
(§7.5.3.5)よりも優れたコンバージョンターゲットです
§7.5.3.5で見てみましょう:
二つの異なる種類を考える
T1
とT2
、T1
より優れた変換対象でT2
、以下のうちの少なくとも1つが保持している場合:
- 以下からの暗黙的な変換
T1
にはT2
存在している、との暗黙の変換T2
にはT1
存在しませんT1
はT2
符号付き整数型であり、符号なし整数型です。
したがって、からまたはのColor
いずれかに変換しています。これらのルールに従ってどちらが良いですか?Object
Int32
Color
には、Object
Object
への暗黙の変換はありませんColor
(明らかに)Color
への暗黙の変換はありませんInt32
(これらはC#で明示的です)Int32
への暗黙の変換はありませんColor
(を除く0
)仕様§6.1:
次の変換は、暗黙的な変換として分類されます。
- ID変換
- 暗黙の数値変換
- 暗黙的な列挙変換。
- 暗黙のnull許容変換
- ヌルリテラル変換
- 暗黙の参照変換
- ボクシングのコンバージョン
- 暗黙の動的変換
- 暗黙の定数式変換
- ユーザー定義の暗黙的な変換
- 匿名関数の変換
- メソッドグループの変換
暗黙の数値変換では列挙型については言及されておらず、暗黙の列挙変換ではその逆が処理されます。
暗黙的な列挙型変換により、decimal-integer-literal
0
を任意の列挙型および基になる型が列挙型であるnull許容型に変換できます。後者の場合、変換は、基になる列挙型に変換し、結果をラップすることによって評価されます(§4.1.10)。
列挙型はボクシング変換によって処理されます(§6.1.7):
ボクシング変換では、値型を暗黙的に参照型に変換できます。ボクシングの変換は、任意の存在する非null許容値型へ
object
とdynamic
に、System.ValueType
及び任意に界面型によって実装非null許容値型。さらに、列挙型は型に変換できますSystem.Enum
。
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加