1.値型と参照型における代入の違い
まずはじめにIClonableインターフェイスを用いたインスタンスコピーの方法について検証してみようと思うのですが、その前に値型と参照型の代入における動作の違いについて軽くおさらいしておきたいと思います。
|
001 002 003 004 005 006 007 008 009 010 011 012 013 014 015 016 017 018 019 020 021 022 023 024 025 026 027 028 029 030 031 032 033 034 035 036 037 038 039 040 041 042 043 044 045 046 047 048 049 050 051 052 053 054 055 056 057 |
Module ClonableAndDisposable ' 参照型 Class ReferencialTypeMusume Public Name As String End Class ' 値型 Structure ValueTypeMusume Public Name As String End Structure ' アプリケーションのエントリーポイント Sub Main() ' 参照型の場合 Dim r1 As New ReferencialTypeMusume(), r2 As New ReferencialTypeMusume() r1.Name = "加護亜依" r2.Name = "石川梨華" Console.WriteLine("r1.Name: {0}, r2.Name: {1}", r1.Name, r2.Name) ' 「参照」を代入 r1 = r2 r2.Name = "高橋愛" Console.WriteLine("r1.Name: {0}, r2.Name: {1}", r1.Name, r2.Name) ' 単なる改行 Console.WriteLine() ' 値型の場合 Dim v1 As New ValueTypeMusume(), v2 As New ValueTypeMusume() v1.Name = "加護亜依" v2.Name = "石川梨華" Console.WriteLine("v1.Name: {0}, v2.Name: {1}", v1.Name, v2.Name) ' 「値」を代入 v1 = v2 v2.Name = "高橋愛" Console.WriteLine("v1.Name: {0}, v2.Name: {1}", v1.Name, v2.Name) End Sub End Module |
| 出力結果 | |
r1.Name: 加護亜依, r2.Name: 石川梨華 r1.Name: 高橋愛, r2.Name: 高橋愛 r1.Name: 加護亜依, r2.Name: 石川梨華 r1.Name: 石川梨華, r2.Name: 高橋愛 Press any key to continue | |
|
001 002 003 004 005 006 007 008 009 010 011 012 013 014 015 016 017 018 019 020 021 022 023 024 025 026 027 028 029 030 031 032 033 034 035 036 037 038 |
Module ClonableAndDisposable ' 参照型 Class ReferencialTypeMusume Public Name As String Public Age As Integer Public BloodType As String End Class ' アプリケーションのエントリーポイント Sub Main() ' インスタンスを生成 Dim r1 As New ReferencialTypeMusume(), r2 As New ReferencialTypeMusume() ' インスタンスを初期化 With r1 .Name = "加護亜依" .Age = 15 .BloodType = "AB" End With ' インスタンスのフィールドをコピー With r2 .Name = r1.Name .Age = r1.Age .BloodType = r1.BloodType End With End Sub End Module |
|
001 002 003 004 005 006 007 008 009 010 011 012 013 014 015 016 017 018 019 020 021 022 023 024 025 026 027 028 029 030 031 032 033 034 035 036 037 038 039 040 041 042 043 044 045 046 047 048 049 050 051 052 053 054 055 056 |
Module ClonableAndDisposable ' 参照型 Class ReferencialTypeMusume ' 様々なスコープを持つフィールド Public Name As String Protected Age As Integer Private BloodType As String ' コンストラクタ (初期化用) Public Sub New(ByVal name As String, ByVal age As Integer, ByVal bloodType As String) Me.Name = name Me.Age = age Me.BloodType = bloodType End Sub ' コンストラクタ (コピー用) Public Sub New(ByVal musume As ReferencialTypeMusume) Me.Name = musume.Name Me.Age = musume.Age Me.BloodType = musume.BloodType End Sub ' インスタンスの状態を表示するためのメソッド Public Overrides Function ToString() As String Return Me.Name + " " + Me.Age.ToString() + "歳, " + Me.BloodType + "型" End Function End Class ' アプリケーションのエントリーポイント Sub Main() ' 変数を宣言 Dim r1, r2 As ReferencialTypeMusume ' インスタンスを生成 r1 = New ReferencialTypeMusume("加護亜依", 15, "AB") ' インスタンスのコピーを生成 r2 = New ReferencialTypeMusume(r1) ' 状態を表示 Console.WriteLine("r1: {0}", r1) Console.WriteLine("r2: {0}", r2) End Sub End Module |
| 出力結果 | |
r1: 加護亜依 15歳, AB型 r2: 加護亜依 15歳, AB型 Press any key to continue | |
|
001 002 003 004 005 006 007 008 009 010 011 012 013 014 015 016 017 018 019 020 021 022 023 024 025 026 027 028 029 030 031 032 033 034 035 036 037 038 039 040 041 042 043 044 045 046 047 048 049 050 051 052 053 054 055 056 057 058 059 060 |
Option Strict On Module ClonableAndDisposable ' 参照型 Class Musume ' IClonableインターフェイスを実装 Implements ICloneable ' 様々なスコープを持つフィールド Public Name As String Protected Age As Integer Private BloodType As String ' コンストラクタ (初期化用) Public Sub New(ByVal name As String, ByVal age As Integer, ByVal bloodType As String) Me.Name = name Me.Age = age Me.BloodType = bloodType End Sub ' Clone()メソッドの実装 Public Function Clone() As Object Implements ICloneable.Clone ' MemberwiseClone()メソッドを利用して簡易コピーを生成 Return Me.MemberwiseClone() End Function ' インスタンスの状態を表示するためのメソッド Public Overrides Function ToString() As String Return Me.Name + " " + Me.Age.ToString() + "歳, " + Me.BloodType + "型" End Function End Class ' アプリケーションのエントリーポイント Sub Main() ' 変数を宣言 Dim r1, r2 As Musume ' インスタンスを生成 r1 = New Musume("加護亜依", 15, "AB") ' インスタンスの簡易コピーを生成 r2 = DirectCast(r1.Clone(), Musume) ' 状態を表示 Console.WriteLine("r1: {0}", r1) Console.WriteLine("r2: {0}", r2) End Sub End Module |
| 出力結果 | |
r1: 加護亜依 15歳, AB型 r2: 加護亜依 15歳, AB型 Press any key to continue | |
|
001 002 003 004 005 006 007 008 009 010 011 012 013 014 015 016 017 018 019 020 021 022 023 024 |
Class Musume ' IClonableインターフェイスを実装 Implements ICloneable ' 途中省略 ' 戻り値が型指定された公開されるClone()メソッド Public Function Clone() As Musume Return DirectCast(Me.MemberwiseClone(), Musume) End Function ' 非公開のClone()メソッド Private Function CloneMyself() As Object Implements ICloneable.Clone Return Me.Clone() End Function End Class |
|
001 002 003 004 005 006 007 008 009 010 011 012 013 014 015 016 017 018 019 020 021 022 023 024 025 026 027 028 029 030 031 032 033 034 035 036 037 038 039 040 041 042 043 044 045 046 047 048 049 050 051 052 053 054 055 056 057 058 059 060 061 062 063 064 065 066 067 068 069 070 071 072 073 074 075 076 077 078 079 080 081 082 083 084 085 086 087 088 089 090 091 092 093 094 095 096 097 098 099 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 |
Option Strict On Module ClonableAndDisposable ' Musumeから参照される型 Class Group ' IClonableインターフェイスを実装 Implements ICloneable ' 値型フィールド Public Name As String ' コンストラクタ Public Sub New(ByVal name As String) Me.Name = name End Sub ' 戻り値が型指定された公開されるClone()メソッド Public Function Clone() As Group Return DirectCast(Me.MemberwiseClone(), Group) End Function ' 非公開のClone()メソッド Private Function CloneMyself() As Object Implements ICloneable.Clone Return Me.Clone() End Function End Class ' コピー対象となるクラス Class Musume ' IClonableインターフェイスを実装 Implements ICloneable ' 値型フィールド Public Name As String ' 参照型フィールド Public Belonging As Group ' コンストラクタ Public Sub New(ByVal name As String, ByVal belonging As Group) Me.Name = name Me.Belonging = belonging End Sub ' 戻り値が型指定された公開されるClone()メソッド Public Function Clone() As Musume Return DirectCast(Me.MemberwiseClone(), Musume) End Function ' 非公開のClone()メソッド Private Function CloneMyself() As Object Implements ICloneable.Clone Return Me.Clone() End Function ' インスタンスの状態を表示するためのメソッド Public Overrides Function ToString() As String If Me.Belonging Is Nothing Then Return Me.Name Else Return Me.Name + " (" + Me.Belonging.Name + ")" End If End Function End Class ' アプリケーションのエントリーポイント Sub Main() ' 所属グループ Dim g As New Group("モーニング娘。") ' 変数を宣言 Dim m1, m2 As Musume ' インスタンスを生成 m1 = New Musume("加護亜依", g) ' インスタンスの簡易コピーを生成 m2 = m1.Clone m2.Name = "紺野あさ美" ' 状態を表示 Console.WriteLine("m1: {0}", m1) Console.WriteLine("m2: {0}", m2) ' Belongingメンバの値を比較 Console.WriteLine("m1.Belonging Is m2.Belonging: {0}", m1.Belonging Is m2.Belonging) End Sub End Module |
| 出力結果 | |
m1: 加護亜依 (モーニング娘。) m2: 紺野あさ美 (モーニング娘。) m1.Belonging Is m2.Belonging: True Press any key to continue | |
|
001 002 003 004 005 006 007 008 009 010 011 012 013 014 015 016 017 018 019 020 021 022 023 024 025 026 027 028 029 |
Class Musume ' 途中省略 ' 戻り値が型指定された公開されるClone()メソッド Public Function Clone() As Musume ' インスタンスの簡易コピーを作成 Dim inst As Musume = DirectCast(Me.MemberwiseClone(), Musume) ' 参照型フィールドであるBelongingフィールドのコピーを生成 If Not Me.Belonging Is Nothing Then inst.Belonging = Me.Belonging.Clone() End If ' 生成されたコピーを返す Return inst End Function ' 途中省略 End Class |
| 出力結果 | |
m1: 加護亜依 (モーニング娘。) m2: 紺野あさ美 (モーニング娘。) m1.Belonging Is m2.Belonging: False Press any key to continue | |
|
001 002 003 004 005 006 007 008 009 010 011 012 013 014 015 016 017 018 019 020 021 022 023 024 025 026 027 028 029 030 031 032 033 034 035 036 037 038 039 040 041 |
Module ClonableAndDisposable Class SampleClass Public Sub New() OutputMessage("コンストラクタが呼び出されました。") End Sub Protected Overrides Sub Finalize() OutputMessage("デストラクタが呼び出されました。") End Sub End Class ' アプリケーションのエントリーポイント Sub Main() OutputMessage("アプリケーションが開始されました。") OutputMessage("インスタンスを生成します。") Dim inst As New SampleClass() OutputMessage("インスタンスが生成されました。") OutputMessage("アプリケーションが終了しました。") End Sub ' メッセージを表示するメソッド Sub OutputMessage(ByVal msg As String) Debug.WriteLine("Ticks " + DateTime.Now.Ticks.ToString() + ": " + msg) End Sub End Module |
| 実行結果 | |
・一回目 Ticks 631849925642777328: アプリケーションが開始されました。 Ticks 631849925650588560: インスタンスを生成します。 Ticks 631849925650688704: コンストラクタが呼び出されました。 Ticks 631849925650688704: インスタンスが生成されました。 Ticks 631849925650688704: アプリケーションが終了しました。 Ticks 631849925650888992: デストラクタが呼び出されました。 ・二回目 Ticks 631849925719988352: アプリケーションが開始されました。 Ticks 631849925727799584: インスタンスを生成します。 Ticks 631849925727799584: コンストラクタが呼び出されました。 Ticks 631849925727899728: インスタンスが生成されました。 Ticks 631849925727899728: アプリケーションが終了しました。 Ticks 631849925728100016: デストラクタが呼び出されました。 ・三回目 Ticks 631849925852879440: アプリケーションが開始されました。 Ticks 631849925860490384: インスタンスを生成します。 Ticks 631849925860590528: コンストラクタが呼び出されました。 Ticks 631849925860790816: インスタンスが生成されました。 Ticks 631849925860790816: アプリケーションが終了しました。 Ticks 631849925860991104: デストラクタが呼び出されました。 | |
|
001 002 003 004 005 006 007 008 009 010 011 012 013 014 015 016 017 018 019 020 021 022 023 024 025 026 027 028 029 030 031 032 033 034 035 036 037 038 039 040 041 042 043 044 045 046 047 048 049 050 |
Module ClonableAndDisposable Class SampleClass ' IDisposableインターフェイスを実装 Implements IDisposable Public Sub New() OutputMessage("コンストラクタが呼び出されました。") End Sub Public Sub Dispose() Implements IDisposable.Dispose OutputMessage("Dispose()メソッドが呼び出されました") End Sub End Class ' アプリケーションのエントリーポイント Sub Main() OutputMessage("アプリケーションが開始されました。") OutputMessage("インスタンスを生成します。") Dim inst As New SampleClass() OutputMessage("インスタンスが生成されました。") OutputMessage("インスタンスを解放します。") inst.Dispose() OutputMessage("インスタンスを解放されました。") OutputMessage("アプリケーションが終了しました。") End Sub ' メッセージを表示するメソッド Sub OutputMessage(ByVal msg As String) Debug.WriteLine("Ticks " + DateTime.Now.Ticks.ToString() + ": " + msg) End Sub End Module |
| 実行結果 | |
Ticks 631849931316335504: アプリケーションが開始されました。 Ticks 631849931324747600: インスタンスを生成します。 Ticks 631849931324747600: コンストラクタが呼び出されました。 Ticks 631849931324747600: インスタンスが生成されました。 Ticks 631849931324847744: インスタンスを解放します。 Ticks 631849931324847744: Dispose()メソッドが呼び出されました Ticks 631849931324947888: インスタンスを解放されました。 Ticks 631849931325148176: アプリケーションが終了しました。 | |
|
001 002 003 004 005 006 007 008 009 010 011 012 013 014 015 016 017 018 019 020 021 022 023 024 025 026 027 028 029 030 031 032 033 034 035 036 037 038 039 040 041 042 043 044 045 046 047 048 049 050 051 052 053 054 055 056 057 058 059 060 061 062 063 064 065 066 |
Imports System.IO Module ClonableAndDisposable Class SampleClass ' IDisposableインターフェイスを実装 Implements IDisposable ' すでにインスタンスが解放されたかを保存する Private disposed As Boolean ' コンストラクタ Public Sub New() disposed = False OutputMessage("コンストラクタが呼び出されました") End Sub ' デストラクタ Protected Overrides Sub Finalize() Dispose() End Sub ' Dispose()メソッド Public Sub Dispose() Implements IDisposable.Dispose If Not disposed Then OutputMessage("Dispose()メソッドが呼び出されました") disposed = True End If End Sub End Class ' アプリケーションのエントリーポイント Sub Main() OutputMessage("アプリケーションが開始されました。") OutputMessage("インスタンスが作成されます。") Dim inst As New SampleClass() OutputMessage("インスタンスが作成されました。") OutputMessage("アプリケーションが終了されます。") End Sub ' メッセージを表示するメソッド Sub OutputMessage(ByVal msg As String) Debug.WriteLine("Ticks " + DateTime.Now.Ticks.ToString() + ": " + msg) End Sub End Module |
| 実行結果 | |
Ticks 631850037169421520: アプリケーションが開始されました。 Ticks 631850037181639088: インスタンスが作成されます。 Ticks 631850037181739232: コンストラクタが呼び出されました Ticks 631850037181739232: インスタンスが作成されました。 Ticks 631850037181739232: アプリケーションが終了されます。 Ticks 631850037181839376: Dispose()メソッドが呼び出されました。 | |