- PR -

長い文字列のハードコーディング

投稿者投稿内容
ぼのぼの
ぬし
会議室デビュー日: 2004/09/16
投稿数: 544
投稿日時: 2008-01-19 18:28
元スレ:http://www.atmarkit.co.jp/bbs/phpBB/viewtopic.php?topic=43033&forum=7

引用:

ひろれいさんの書き込み (2008-01-11 13:39) より:
引用:

ふらわーさんの書き込み (2008-01-11 13:04) より:

SQL文
Dim strSQL As String = ""
strSQL = ""
strSQL += "SELECT "
strSQL += " A.SYAIN_CD,A.SYAIN_NM,D.BUMON_NM "
strSQL += " FROM M_SYAIN A LEFT JOIN M_SYAIN_KBN B ON "
strSQL += " A.SYAINKBN_CD = B.SYAINKBN_CD "
strSQL += " LEFT JOIN M_SYOZOKU C ON "
strSQL += " A.EIGYO_CD = C.EIGYO_CD "
strSQL += " LEFT JOIN M_BUMON D ON "
strSQL += " A.BUMON_CD = D.BUMON_CD "
strSQL += " ORDER BY A.SYAIN_CD "


関係ないけど、気になったので。

StringBuilder の方がよくないですか?
細切れにしている理由もよく分かりませんけど



引用:

じゃんぬねっとさんの書き込み (2008-01-11 13:51) より:
引用:

ひろれいさんの書き込み (2008-01-11 13:39) より:

StringBuilder の方がよくないですか?
細切れにしている理由もよく分かりませんけど


C# なら逐語的リテラル マンセーなんですけどね。 VB では皆さんどのように書いているのでしょうね? 脱線しそうなので別スレッドか Blog か何かで展開してみますか。




展開されないので別スレ立ててみましたw

素朴な疑問1。
本件は長い文字列を複数行に記述する時の話だと思うのですが、この場合、逐語的リテラルは何か関係あるのでしょうか?

素朴な疑問2。
コンパイラとか最適化とかあんまり詳しくないのですが、下記(1)〜(3)で、コンパイル後、実際に動くときのリソースの使われ方とかって、変わってくるものでしょうか?いや、普通に考えれば全く同じってことはないですよね。(3)は使ってるクラスが違うわけですから。

コード:
(1)
  [VB]
    Dim sql As String = ""
    sql += "SELECT C1, C2, C3"
    sql += " FROM T1"
    sql += " WHERE C1 = @C1"
  [C#]
    string sql = "";
    sql += "SELECT C1, C2, C3";
    sql += " FROM T1";
    sql += " WHERE C1 = @C1";

(2)
  [VB]
    Dim sql As String = "" _
        + "SELECT C1, C2, C3" _
        + " FROM T1" _
        + " WHERE C1 = @C1"
  [C#]
    string sql = ""
        + "SELECT C1, C2, C3"
        + " FROM T1"
        + " WHERE C1 = @C1";

(3)
  [VB]
    Dim sb As New StringBuilder()
    sb.Append("SELECT C1, C2, C3")
    sb.Append(" FROM T1")
    sb.Append(" WHERE C1 = @C1")
    Dim sql As String = sb.ToString()
  [C#]
    StringBuilder sb = new StringBuilder();
    sb.Append("SELECT C1, C2, C3");
    sb.Append(" FROM T1");
    sb.Append(" WHERE C1 = @C1");
    string sql = sb.ToString();


他にもいくつか書き方はあるでしょうけど、長い文字列をハードコーディングしたい状況ってのはよくあること(主にSQL等)ですから、どんな書き方が最も望ましいかは知っておきたいところです。話題としては既出かもしれませんが、よろしければご意見お聞かせください。
ちゃっぴ
ぬし
会議室デビュー日: 2004/12/10
投稿数: 873
投稿日時: 2008-01-19 20:28
というより、parameterized queryもしくは stored procedure 利用しないの?なんでっていうのが正直な感想ですが。

本題の方は reference 読みましたか?

StringBuilder クラス

パフォーマンスに関する考慮事項 を参照

Memory 確保の方法が違います。
_________________
todo
ぬし
会議室デビュー日: 2003/07/23
投稿数: 682
投稿日時: 2008-01-19 21:38
引用:

素朴な疑問2。
コンパイラとか最適化とかあんまり詳しくないのですが、下記(1)〜(3)で、コンパイル後、実際に動くときのリソースの使われ方とかって、変わってくるものでしょうか?いや、普通に考えれば全く同じってことはないですよね。(3)は使ってるクラスが違うわけですから。



MSILのコードを見てみましょう。
http://www.atmarkit.co.jp/fdotnet/dotnettips/098exttool/exttool.html


引用:

他にもいくつか書き方はあるでしょうけど、長い文字列をハードコーディングしたい状況ってのはよくあること(主にSQL等)ですから、どんな書き方が最も望ましいかは知っておきたいところです。



固定のSQL文であれば、私ならこう書きます。

コード:
(4)
  [C#]
    const string sql = ""
        + "SELECT C1, C2, C3"
        + " FROM T1"
        + " WHERE C1 = @C1";

ぼのぼの
ぬし
会議室デビュー日: 2004/09/16
投稿数: 544
投稿日時: 2008-01-19 22:17
引用:

ちゃっぴさんの書き込み (2008-01-19 20:28) より:
本題の方は reference 読みましたか?

StringBuilder クラス

パフォーマンスに関する考慮事項 を参照

Memory 確保の方法が違います。


読んできますた(`・ω・´)

動的に何回も連結する必要がある場合はStringBuilderですね。

しかし、どちらかというと私が本題にしてるのは固定の方です。
固定の場合、先の例だと(1)は論外、(3)も実は必要なくて、(2)がベストということ?

引用:

todoさんの書き込み (2008-01-19 21:38) より:
固定のSQL文であれば、私ならこう書きます。

コード:
(4)
  [C#]
    const string sql = ""
        + "SELECT C1, C2, C3"
        + " FROM T1"
        + " WHERE C1 = @C1";




それとも、(1)と(2)は実は同じ動きになってしまい、ベストなのはローカルメソッド内で1回しか使わないようなローカル変数でもconstキーワードをつけて(4)ということでしょうか?

引用:

MSILのコードを見てみましょう。
http://www.atmarkit.co.jp/fdotnet/dotnettips/098exttool/exttool.html


これは時間がかかりそうなので、気力のあるときにじっくりやってみたいと思います。(^^;
IIJIMAS
ベテラン
会議室デビュー日: 2006/12/06
投稿数: 77
投稿日時: 2008-01-20 00:58
引用:

ぼのぼのさんの書き込み (2008-01-19 18:28) より:
素朴な疑問1。
本件は長い文字列を複数行に記述する時の話だと思うのですが、この場合、逐語的リテラルは何か関係あるのでしょうか?


単に
コード:

[C#]
string sql = @"
SELECT C1, C2, C3
FROM T1
WHERE C1 = @C1
";


のように書けて、わかりやすいかまたはSQL文として意味のあるコードそのままでC#コードに1つの文字列として書けるということだと思います。
引用:

素朴な疑問2。
コンパイラとか最適化とかあんまり詳しくないのですが、下記(1)〜(3)で、コンパイル後、実際に動くときのリソースの使われ方とかって、変わってくるものでしょうか?いや、普通に考えれば全く同じってことはないですよね。(3)は使ってるクラスが違うわけですから。


VBでリテラル文字列だったら個人的には(2)でよいと思いますが。

方法 : 複数行のリテラル文字列を生成する (Visual Basic)
http://msdn2.microsoft.com/ja-jp/library/5chcthbw(VS.80).aspx

パフォーマンスを計測して比べるなら、ループに入れて
Stopwatch クラス
http://msdn2.microsoft.com/ja-jp/library/system.diagnostics.stopwatch.aspx
を使えばよいのではないでしょうか。

[ メッセージ編集済み 編集者: IIJIMAS 編集日時 2008-01-20 00:59 ]
ぼのぼの
ぬし
会議室デビュー日: 2004/09/16
投稿数: 544
投稿日時: 2008-01-20 01:35
引用:

IIJIMASさんの書き込み (2008-01-20 00:58) より:
引用:

ぼのぼのさんの書き込み (2008-01-19 18:28) より:
素朴な疑問1。
本件は長い文字列を複数行に記述する時の話だと思うのですが、この場合、逐語的リテラルは何か関係あるのでしょうか?


単に
コード:
  [C#]
    string sql = @"
            SELECT C1, C2, C3
            FROM T1
            WHERE C1 = @C1
            ";


のように書けて、わかりやすいかまたはSQL文として意味のあるコードそのままでC#コードに1つの文字列として書けるということだと思います。


このコードだと、インデント用の改行やスペースがそのままSQLに含まれてしまいませんか?

引用:

VBでリテラル文字列だったら個人的には(2)でよいと思いますが。

方法 : 複数行のリテラル文字列を生成する (Visual Basic)
http://msdn2.microsoft.com/ja-jp/library/5chcthbw(VS.80).aspx


どうも、複数行の意味を誤解されてしまったようですね(^^;
私の書いたサンプルコードを良く見てください。結果生成される文字列のどこにも改行は含まれません。
複数行の文字列を記述したいのではなく、長い文字列をソースコード上複数行に記述するときのお話です。

引用:

パフォーマンスを計測して比べるなら、ループに入れて
Stopwatch クラス
http://msdn2.microsoft.com/ja-jp/library/system.diagnostics.stopwatch.aspx
を使えばよいのではないでしょうか。


本音を言うと、パフォーマンスはあまり気にしてません(爆)。
10年前ならともかく、昨今のハードウェアスペックだとこんなとこで性能差は殆ど出ないと思ってます。
勿論こだわる方に言わせれば塵も積もればなんでしょうが、少なくともシステムのボトルネックになるほどの差はでないんではないかと。
DBのインデックスがちゃんと効いてるかとかそっちの方が全然大きいわけで。

なので、これはどちらかというと少しでもお行儀の良いコードを書きたいという、精神衛生上の問題なのです。
従って、単にパフォーマンスというよりは、可読性とかも含めた議論になるかと思ってます。
IIJIMAS
ベテラン
会議室デビュー日: 2006/12/06
投稿数: 77
投稿日時: 2008-01-20 04:00
引用:

ぼのぼのさんの書き込み (2008-01-20 01:35) より:
このコードだと、インデント用の改行やスペースがそのままSQLに含まれてしまいませんか?


文字列の内容を実行する言語で改行やスペースのために意図した結果が得られない場合は仕方ありませんが、そうでないかぎり、この方法は「見やすく」かけると思います。

引用:

なので、これはどちらかというと少しでもお行儀の良いコードを書きたいという、精神衛生上の問題なのです。
従って、単にパフォーマンスというよりは、可読性とかも含めた議論になるかと思ってます。


であれば、やはり見やすい(2)か長くても1行で書くのがよいと思います。
文字列がSQL等他の言語のコードである場合、プログラムコードファイル上でもなるべくその標準的な形を崩さないものがよいと思います。

[ メッセージ編集済み 編集者: IIJIMAS 編集日時 2008-01-20 04:06 ]
マシュマロ
会議室デビュー日: 2007/08/11
投稿数: 12
投稿日時: 2008-01-20 11:41
こんにちは、

私が管理者なら、
・(1)、(2)でもOK。ただ、言語の仕様上可能なら(2)
・ループ内での文字列連結は(3)のようなバッファリングクラスで連結

でルール化します。
逐語的リテラルは1行で使用する(ファイルパスなどで、エスケープを不要にする目的)もののみ許容。

逐語的リテラルの改行やタブ、とくにタブがそのまま反映されるのは便利と言うより、管理上リスクに感じます。

スキルアップ/キャリアアップ(JOB@IT)