.NETで文字列を連結すると効率が悪いといわれています。
例えばこんな具合です。
Dim str As String
str = "雨にも負けず"
str = str & "風にも負けず" & vbCrLf
str = str & "雪にも夏の暑さにも負けぬ" & vbCrLf
str = str & "丈夫なからだをもち" & vbCrLf
str = str & "慾はなく" & vbCrLf
str = str & "決して怒らず" & vbCrLf
str = str & "いつも静かに笑っている" & vbCrLf
マイクロソフトでは、StringBuilderを使うように推奨しています。
(ただし、文字列が決まっていればStringの連結が勝っているようです。)
そこでStringBuilderを自分の都合に合わせてを改良したいと思います。
StringBuilderが継承できれば楽なのですが、StringBuilderは継承できませんので、StringBuilderを要素にもつ独自のStringBuilderを作成しました。
主要な部分は次のとおりです。
Public Class MyStringBuilder
Private m_sb As StringBuilder
....
Public Sub Append(ByVal strIn As String, Optional ByVal blnReset As Boolean = False)
If blnReset Then Reset()
m_sb.Append(strIn)
End Sub
Public Sub AppendFormat(ByVal strFormat As String, ByVal ParamArray args() As Object)
m_sb.AppendFormat(strFormat, args)
End Sub
.....
Public Function Conc(ByVal strAdd As String, Optional ByVal blnReset As Boolean = False)
If blnReset Then Reset()
m_sb.Append(strAdd)
m_sb.Append(ControlChars.CrLf)
End Function
Public Function ConcFormat(ByVal strFormat As String, ByVal ParamArray args() As Object)
m_sb.AppendFormat(strFormat, args)
m_sb.Append(ControlChars.CrLf)
End Function
Appendは機能的にはStgringBuilderと同じです。
Concは次のようにメッセージの作成等改行を入れたいとき使います。先の例では、
Dim MySB As New MyStingBuilder
With MySB
.Conc("雨にも負けず")
.Conc("風にも負けず")
.Conc("雪にも夏の暑さにも負けぬ")
.Conc("丈夫なからだをもち")
.Conc("慾はなく")
.Conc("決して怒らず")
.ConcFormat("{0}{1}{2}", "いつも", "静かに", "笑っている")
End With
MessageBox.Show(MySB.ToString, "MyStringBuilder", )
読みやすくなっていると思いませんか。
SQLでは改行を入れるといけません。プロパーのStringBuilderのAppendでいいのですが、一貫して[MyStringBuilder]を使いたいので[MyStringBuilder]用のAppendを定義しています。次のように使います。
Dim MySB As New MyStingBuilder
With MySB
.Append("Select * From 書籍")
.AppendFormat(" Where 著者名='{0}'", "司馬 遼太郎")
.AppendFormat(" And 出版日 Between '{0}' And {1}", _
New Date(1990, 1, 1), New Date(1996, 2, 1))
End With
連続する二つの句の間にスペースが必要なので、実際にはスペースを入れるようなメソッドを用意しています。
ところで、ここには誤りがあります。
最後の文の{1}プレースホルダをクォートする必要があります。
日付リテラルはSQL Serverではシングルクォートで、Accessでは#で囲む必要があります。
私は、ディレクティブを使ってラッパー関数を用意しています。
Public Function DateWrapper(ByVal dte As Date) As String
#If DB = "SQLServer" Then
Return (String.Format("'{0}'", dte.ToShortDateString))
#ElseIf DB = "Access"
Return (String.Format("#{0}#", dte.ToShortDateString))
#Else
....
#End If
End Function
[DateWrapper]を通せば、DBに何を使っているかその都度気にする必要はありません。従って先の例は次の通りです。
.AppendFormat(" And 出版日 Between {0} And {1}", _
DateWrapper(New Date(1990, 1, 1)), DateWrapper(New Date(1996, 2, 1)))