- PR -

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

投稿者投稿内容
よねKEN
ぬし
会議室デビュー日: 2003/08/23
投稿数: 472
投稿日時: 2008-01-21 11:11
誤情報を流してしまい申し訳ありませんでした。

引用:

rainさんの書き込み (2008-01-21 10:42) より:
引用:

よねKENさんの書き込み (2008-01-21 10:16) より:

すっかり忘れていましたが、VBは複数行を継続して記述する際は、
行継続文字(スペース+"_")を付加する必要があるのとその回数に制限があるので、



回数制限があるという話は初めて聞いたので調べてみました。

・VBAでこんな話題があがっていました。
エラー : 行接続文字を使いすぎています
・MSDN(VisualStudio2005に付属のもの)では、特にそのような説明は見当たりませんでした。
・VB.net2005で行継続文字を使って1000行くらい連結してみましたが、ビルドは通りました。

VB6以前だと発生するが、VB.netになって大丈夫になったのかな? と予想しましたが、
VB6の確認環境を持っていないのでわかりません。



rainさん、フォローありがとうございます。
VB6(VB5?)以前にあった制限事項でしたが(昔、実験で確認したのでは25行くらいでした)、VB.netになってどうも制限はなくなってそうですね。
とりあえず200行くらい行継続をしたソースをVB7.1、VB8.0でコンパイルして実行してみましたが、問題なく動きました。
(エディタで作成+コンパイラでビルドして実行)
じゃんぬねっと
ぬし
会議室デビュー日: 2004/12/22
投稿数: 7811
お住まい・勤務地: 愛知県名古屋市
投稿日時: 2008-01-21 12:57
引用:

よねKENさんの書き込み (2008-01-21 11:11) より:

VB6(VB5?)以前にあった制限事項でしたが(昔、実験で確認したのでは25行くらいでした)


VB6 だと 24 行までは OK ですが、25 行で NG になります。(調べたことがあります)

_________________
C# と VB.NET の入門サイト
じゃんぬねっと日誌
Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2008-01-21 21:55
引用:

ぼのぼのさんの書き込み (2008-01-20 14:17) より:
SQLを実行するだけなら意図した結果は得られるでしょうね。
しかし、実行前にSQLをログに記録する、としたらどうでしょう?
タブ文字や改行文字がログ上で特殊な意味を持つ場合って、ありますよね。
#これが「そうでないかぎり」の部分になるかな


 それは、別々に考えるべきでしょう。
 MessageBox で表示するテキスト(エラーメッセージとか)を考えます。このとき、画面上の有効な範囲や、表現上の都合で改行したい場合があります。このとき、画面上のメッセージと、ログ用のメッセージを、別々に作成するのでしょうか?

 それよりも、インジェクション系の脆弱性に対応するのと同じ考え方をするのがよいと思います。つまり、「ログ出力に対しては、改行やタブが特殊な意味を持つため、出力する直前に他の文字に置き換える」と。いま、SQL を2箇所に出力することが出てきました。DBMS とログです。DBMS に対する SQL インジェクションへの対応と、ログに対するフォーマットへの対応は、別々に行ってしかりではないでしょうか。


 私は、今は C++ 使っていますので、楽ですね。
コード:
char* str = "1行目"
            "2行目"
            "3行目";


ハニワ祭り
大ベテラン
会議室デビュー日: 2005/11/15
投稿数: 115
投稿日時: 2008-01-21 23:55
VBだと可読性、メンテナンス性重視で、こんな感じに書くことが多いですね。
(3)'

Dim sb As New StringBuilder()
With sb
.Append("SELECT ").Append(VbCrLf)
.Append(" C1 ").Append(VbCrLf)
.Append(",C2 ").Append(VbCrLf)
.Append(",C3 ").Append(VbCrLf)
.Append("FROM T1 ").Append(VbCrLf)
.Append("WHERE C1 = @C1 ").Append(VbCrLf)
End With

改行は、プロファイラから拾う時の為です。


[ メッセージ編集済み 編集者: ハニワ祭り 編集日時 2008-01-22 00:02 ]
burton999
ぬし
会議室デビュー日: 2003/10/06
投稿数: 898
お住まい・勤務地: 東京
投稿日時: 2008-01-22 10:03
引用:

ハニワ祭りさんの書き込み (2008-01-21 23:55) より:
VBだと可読性、メンテナンス性重視で、こんな感じに書くことが多いですね。
(3)'

Dim sb As New StringBuilder()
With sb
.Append("SELECT ").Append(VbCrLf)
.Append(" C1 ").Append(VbCrLf)
.Append(",C2 ").Append(VbCrLf)
.Append(",C3 ").Append(VbCrLf)
.Append("FROM T1 ").Append(VbCrLf)
.Append("WHERE C1 = @C1 ").Append(VbCrLf)
End With

改行は、プロファイラから拾う時の為です。


[ メッセージ編集済み 編集者: ハニワ祭り 編集日時 2008-01-22 00:02 ]



AppendLineを使ったほうがいいと思います。。。
ぼのぼの
ぬし
会議室デビュー日: 2004/09/16
投稿数: 544
投稿日時: 2008-01-26 13:38
いろいろなご意見ありがとうございます。

結構皆さんパフォーマンスより可読性重視だったのが意外でした。
時流ですかね(笑)

Tdnr_Symさんのおかげで私の一番知りたかったことは解決しました。
これで今後は(2)を使うにあたって躊躇しなくてすみますです。

実はこんな選択肢も用意してたのですが、もーほんとにどれでも良さそうですねw
自分が読みやすく、書きやすく、直しやすいと思うやつでいこーかと思います。

でもせっかくなので、一応置いときますね。

選択肢1
コード:
(A)
public const string SomeSql = "SELECT * FROM TABLE1 WHERE ID = @ID";

(B)
private const string someSql = "SELECT * FROM TABLE1 WHERE ID = @ID";

public static string SomeSql {
    get { return someSql; }
}

(C)
public static string SomeSql {
    get {
        const string sql = "SELECT * FROM TABLE1 WHERE ID = @ID";
        return sql;
    }
}

(D)
public static string SomeSql {
    get {
        return "SELECT * FROM TABLE1 WHERE ID = @ID";
    }
}



選択肢2
コード:
(ア)
public static string SomeSql(string tableName) {
    return "SELECT * FROM " + tableName + " WHERE ID = @ID"; 
}

(イ)
public static string SomeSql(string tableName) {
    return string.Format("SELECT * FROM {0} WHERE ID = @ID", tableName);
}

(ウ)
public static string SomeSql(string tableName) {
    StringBuilder sb = new StringBuilder();
    sb.Append("SELECT * FROM ").Append(tableName).Append(" WHERE ID = @ID");
    return sb.ToString();
}

(エ)
public static string SomeSql(string tableName) {
    StringBuilder sb = new StringBuilder();
    sb.AppendFormat("SELECT * FROM {0} WHERE ID = @ID", tableName);
    return sb.ToString();
}

(オ)
public static string SomeSql(string tableName) {
    StringWriter sw = new StringWriter();
    sw.Write("SELECT * FROM {0} WHERE ID = @ID", tableName);
    return sw.ToString();
}

ykSiR
会議室デビュー日: 2006/10/03
投稿数: 16
投稿日時: 2008-01-26 14:47
まとめに入られている時に話がずれて恐縮なのですが、
引用:

ぼのぼのさんの書き込み (2008-01-26 13:38) より:
選択肢1
コード:
(A)
public const string SomeSql = "SELECT * FROM TABLE1 WHERE ID = @ID";




これは避けた方が良いのではないでしょうか?

constだとコンパイル時に埋め込まれるので、別アセンブリから参照される場合などに思わぬバグの原因になりそうな気がします。

コード:
public static readonly string SomeSql = "SELECT * FROM TABLE1 WHERE ID = @ID";


こちらでいかがでしょう?
Tdnr_Sym
ぬし
会議室デビュー日: 2005/09/13
投稿数: 464
お住まい・勤務地: 明石・神戸
投稿日時: 2008-01-26 18:05
こんばんは。

引用:

ykSiRさんの書き込み (2008-01-26 14:47) より:
constだとコンパイル時に埋め込まれるので、別アセンブリから参照される場合などに思わぬバグの原因になりそうな気がします。



もしかして、ここの記事↓で書かれているようなことを仰っていますか?
What is the difference between Const and Readonly?
引用:

The first four rows show the Readonly, where you can see the ldsfld which is MSIL instruction for pushing the value of a static field into the stack!
The other four rows show the Const, Where you can see ldc,ldstr instead of ldsfld which means that Const doesn't behave like Readonly, Const is very similar to to #define in c, don't have its own location as global, Const is just written as number/string (hard coded) at the compile time.

After we know this simple transformation at the compile time,
we will see an example including two DLLs:

A: hold the const vars.
B: uses A's const vars.
When we made a change at A (changing one of the consts) we can't only compile it and replace the DLL at the bin directory, we should also compile this with the DLL who use it (B in our case).
So it will change also the hard coded numbers!



まあ参照している側がリビルドし直せばよいだけですが、
変更する可能性のある定数は、あんまりpublic constは望ましくないかもしれませんね。文字列に限らず。

これがいいかも。
コード:
internal const string SomeSql = "SELECT * FROM TABLE1 WHERE ID = @ID";


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