さて、今回もアホくさい取り組みをしようと思います。
皆さんもご存知のように、C# では以下のように空ブロック ({ }) を定義することができます。
C# - 空ブロック使用例
private static System.Collections.ArrayList GetWankumaList() {
System.Collections.ArrayList wankumaList = new System.Collections.ArrayList();
{
System.Collections.DictionaryEntry item = new WankumaItem();
item.MemberId = 1;
item.MemberName = "中博俊";
item.Competency = "C#"
wankumaList.Add(item);
}
{
System.Collections.DictionaryEntry item = new WankumaItem();
item.MemberId = 2;
item.MemberName = "じゃんぬねっと";
item.Competency = null;
wankumaList.Add(item);
}
{
System.Collections.DictionaryEntry item = new WankumaItem();
item.MemberId = 3;
item.MemberName = "Jitta";
item.Competency = "ASP.NET"
wankumaList.Add(item);
}
{
System.Collections.DictionaryEntry item = new WankumaItem();
item.MemberId = 4;
item.MemberName = "やねうらお";
item.Competency = "DirectX"
wankumaList.Add(item);
}
{
System.Collections.DictionaryEntry item = new WankumaItem();
item.MemberId = 5;
item.MemberName = "επιστημη";
item.Competency = "C++"
wankumaList.Add(item);
}
return wankumaList;
}
あまり良い例ではないですが、上記は WankumaItem を複数格納した ArrayList のインスタンスを返すコードです。このように、同名の変数 'item' をブロック単位で別物にすることができます。
さて、VB.NET には、空ブロックの機構が備わっていないため、このような書き方はできません。しかし、何らかのブロックを作ってしまえば、代用することができます。(C# でも、同じことが言えますが)
極端に言えば、
VB.NET - 空ブロックを If ステートメントで代用する
Private Function GetWankumaList() As System.Collections.ArrayList
Dim wankumaList As New System.Collections.ArrayList()
' 意味のない If ステートメント
If True Then
Dim item As New WankumaItem()
item.MemberId = 1
item.MemberName = "中博俊"
item.Competency = "C#"
wankumaList.Add(item)
End If
' 意味のない If ステートメント
If True Then
Dim item As New WankumaItem()
item.MemberId = 2
item.MemberName = "じゃんぬねっと"
item.Competency = Nothing
wankumaList.Add(item)
End If
:
:
:
Return wankumaList
End Sub
このように、If True Then ... End If といった、無意味なブロックを作ってしまえば良いわけです。
インスタンス メンバ内のプロシージャであれば、次のように With Me を使うことができます。
VB.NET - 空ブロックを With Me で代用する
Private Function GetWankumaList() As System.Collections.ArrayList
Dim wankumaList As New System.Collections.ArrayList()
' 意味のない With ステートメント
With Me
Dim item As New WankumaItem()
item.MemberId = 1
item.MemberName = "中博俊"
item.Competency = "C#"
wankumaList.Add(item)
End With
' 意味のない With ステートメント
With Me
Dim item As New WankumaItem()
item.MemberId = 2
item.MemberName = "じゃんぬねっと"
item.Competency = Nothing
wankumaList.Add(item)
End With
:
:
:
Return wankumaList
End Sub
VB.NET になってから、使用価値がなくなった With ステートメントを利用するとはオツなものです。
しかしながら、静的なメンバ (Shared | 共有メンバ) では、Me を利用することはできません。そのような場合も考えると、以下のような実装が究極と言えそうです。
VB.NET - 空ブロックを With Block で代用する
' 意味のない定数定義 (せっかくだから、俺はそれっぽい名前を付けるぜ)
Private Const Block As Object = Nothing
Private Function GetWankumaList() As System.Collections.ArrayList
Dim wankumaList As New WankumaItem()
' 意味のない With ステートメント
With Block
Dim item As New WankumaItem()
item.MemberId = 1
item.MemberName = "中博俊"
item.Competency = "C#"
wankumaList.Add(item)
End With
' 意味のない With ステートメント
With Block
Dim item As New WankumaItem()
item.MemberId = 2
item.MemberName = "じゃんぬねっと"
item.Competency = Nothing
wankumaList.Add(item)
End With
' 無論、Nothing でも同じことです (こっちの方が色がついていいかも)
With Nothing
Dim item As New WankumaItem()
item.MemberId = 3
item.MemberName = "Jitta"
item.Competency = "ASP.NET"
wankumaList.Add(item)
End With
:
:
:
Return wankumaList
End Sub
このように、'With Block' という下りで「ブロックであること」が、明示化できています。もちろん、この 'Block' は、Nothing とイコールなのですから、'With Nothing' という書き方でも構いません。
さて、今回のような実装は「ブロックを作らなくとも、別の変数名を定義すれば回避できる」でしょう。しかし、ブロック レベルの変数を使用することで得るメリットがあります。
まず、他のブロックから参照できない (安全な) のは利点のひとつでしょう。他人の改変によって、勝手に触られてイライラすることが少なくなります。他のブロックから参照できないと同時に、他のブロックから「参照されていないことが一目でわかる」ことも大きな利点です。メソッドのコード量が多くなることは普通はないわけですが、使い捨て変数 (COBOLer 的には Work 変数w) であることが一目でわかります。
個人的には、「'同名の' 安易な変数名」が、使えることが最も有効な利点だと思います。普通、変数名には厳密な名前を付けるべきです。しかしながら、あまり重要でない (広い範囲でない) 変数には、むしろ安易な名前をつけるべきだと考えています。
今回の例で考えると、'item' に対して別々の名前をつけた場合、
- 他の変数名が際立たなくなる
- 大した意味はないのに、意味があるかのように見えてしまう
という副作用を生みます。これは、for を使って、配列を取り出す場合の 'ループ変数' に厳密な名前を付けた時の副作用と同じですね。
そういった理由で、使い捨て変数を利用する時に「ブロック変数」を使いたくなることがあります。
それでも、アホくさいとしか思えない方は「メソッドに切り出せばいいだろう」という考えをお持ちだと考えられます。しかし、何でもかんでもメソッドに切り出すと、返って可読性が悪くなることもあります。
そういうわけで、こういうアホくさい記事をたまには書かせてください。(ムリヤリ締めくくりました)