前回、[C#] VB6.0風にC#でデフォルトプロパティを作る | Moonmile Solutions Blog の続きです。と言うか、こっちを先に書かないと訳が分からないですよね。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 | Public Class Form1 ''' <summary> ''' インデックスを利用した例 ''' </summary> ''' <param name="sender"></param> ''' <param name="e"></param> ''' <remarks></remarks> Private Sub Button1_Click(sender As System. Object , e As System.EventArgs) Handles Button1.Click Dim obj As New DefaultClass ' 配列も関数呼び出しも「()」なので、関数呼び出しに見えるのが難点か Debug.Print(obj(10)) Debug.Print(obj( "key" )) Debug.Print(obj.Item(10)) Debug.Print(obj.Item( "key" )) End Sub ''' <summary> ''' 暗黙の型変換を使う ''' </summary> ''' <param name="sender"></param> ''' <param name="e"></param> ''' <remarks></remarks> Private Sub Button2_Click(sender As System. Object , e As System.EventArgs) Handles Button2.Click Dim obj As New DefaultClass Dim name As String = obj Debug.Print( "name:{0}" , name) Dim num As Integer = obj Debug.Print( "num:{0}" , num) End Sub End Class Public Class DefaultClass Public Sub New () Me .ItemName = "DefaultClass" Me .ItemNum = 10 End Sub ''' <summary> ''' デフォルトプロパティを作る ''' </summary> ''' <param name="i"></param> ''' <value></value> ''' <returns></returns> ''' <remarks></remarks> Default Public ReadOnly Property Item(i As Integer ) As String Get Return String .Format( "item-int {0}" , i) End Get End Property Default Public ReadOnly Property Item(name As String ) As String Get Return String .Format( "item-name {0}" , name) End Get End Property Public Property ItemName As String Public Property ItemNum As Integer ''' <summary> ''' 暗黙のキャスト ''' </summary> ''' <param name="obj"></param> ''' <returns></returns> ''' <remarks></remarks> Public Shared Narrowing Operator CType (obj As DefaultClass) As String Return obj.ItemName End Operator Public Shared Narrowing Operator CType (obj As DefaultClass) As Integer Return obj.ItemNum End Operator End Class |
もともと、既定のプロパティという考え方が、VB6.0から来ているので(正確にはVB3.0の頃ですかね?)VB.NET のほうが素直に書けます。
「obj(10)」のようにインデックスを使う場合には、「Default」というキーワードを使います。上記のソースの場合には、Item プロパティを多重定義しているので、Integer 型、String 型の両方の Item プロパティの定義に Default を設定します。
暗黙の変換のほうは「Narrowing」というキーワードですね。これが C# の implicit にあたります。逆に、明示的な変換のほうは「Widening」というキーワード。C# で云えば explicit です。
暗黙の変換を使うと、
1 2 3 4 | Dim name As String = obj Debug.Print( "name:{0}" , name) Dim num As Integer = obj Debug.Print( "num:{0}" , num) |
という書き方ができて、対象のオブジェクトから値を取り出すときに便利です(つーかかえってややこしいかも)。取り出す利用者側として、「name」「num」の型はわかっているので「name = obj」、「num = obj」とやっても、それぞれの string 型、integer 型を類推させることが可能、ということです。普通は「name = obj.name」のように目的のプロパティを指定する訳ですが、取り出す string 型が一種類しかないのであれば「name = obj」としても良かろうという意味ですね。
本当は、「obj = name」のように逆向きも作りたいところなのですが、単純な代入演算子(=演算子)はオーバーライドできないので、無理なのです。仕方がないので二項演算子と組わせた「*=」とか「+=」とかならば可能なので、その話は後日。「+=」はデリゲート関係で使っていますね。