RSS

C#でヒアドキュメント

24 4月

 ちょっと調べて思ったこと。

 ヒアドキュメントっていうのは元々何の用語なのかはっきり知らない(来歴を知っている人がいれば教えていただきたい)が、シェルスクリプトを書くときや、言語的にはPerl、PHPの系統で使われる用語だ。意味としては「エスケープなどを必要とせず改行などを含むことが出来る文字列の記述法」くらいのものと思って良いだろう。
 C#の文字列リテラルでもヒアドキュメントと似たようなことが出来るのだが、呼び名が若干違う。MSDNでは「逐語的文字列リテラル」と表記されているが、他にも、「ヒアストリング」「@-quoted string」のような呼ばれ方もされるようで、どうにも統一性がない。確かに逐語的文字列リテラル…なんて変にややこしいだけの気もする。個人的には「ヒアストリング」がすっきりしてていいかな。

 具体的な記述法はこう、文字列リテラルの頭に@を付ける。

            string filepath = @"c:\hoge\fuga\piyo.xml";

            string strLines = @"エスケープ無しでも
                                改行付き文字列が作れるんだ。";

            string incQuote = @"ちなみに二重引用符は""こんな風に書く""と使える。";

 参考:http://msdn.microsoft.com/ja-jp/library/ms228362.aspx
 
 上記filepathの区切り文字のようにエスケープが必要とされる文字列を記述するのに便利ではある(バックスラッシュは本来なら\\と書かなければならない)。また同様にエスケープが必要な改行も、strLinesのように書くことが出来る(本来は\nなどと書く)。
 ただし「プレーンテキストをそのまま出力したい」という時にはあまり向かないと思う。なぜなら、当然のことだが、インデント用の空白も文字列として含まれるからだ。strLinesをこのまま出力した場合、インデント分だけ二行目の頭に空白が出力されてしまうことになる。どうしても空白が邪魔であれば、左詰めにして書くしかない。

string indentIyayo = @"インデントの空白が嫌なので
左詰めして
書きますよ";

 ただし見た目(=可読性)の問題がある。今はサンプルコードなのでこの程度だが、実際にはもっと深いインデントで書かれるだろう。namespace -> class -> method だけでも3段階程と考えると、1インデント4whitespaceだとして12個も空白があるわけで、そんな中で左詰め記法をしたらソースの可読性は著しく落ちてしまう。まぁこれはHTMLの<pre>タグでも似たような悩みと言えよう。
 ということで、自由に改行するためにヒアストリングを使う場合は「インデントの空白を無視してよい」ような状況、例えば、「通常は出力はしない」とか「あんまりメモリの制約を気にしなくて良い」という状況で使いましょう、ということになる。…まぁ好みの問題かもしれないけど。

 さてこんなヒアストリングだが使いたくなる局面といえば、先ほどのファイルパスの他、SQL文みたいなものをハードコーディングする場合がある。まぁ細かい議論は省略するが、SQL文をヒアストリングで書きたい場合とは要するに「面倒くさい記述をしたくない&可読性も確保したい」時だろう。可読性を考えると左詰めという技法はまず採用出来ない、と、なるとインデント空白を許容しなくてはいけない。
 SQL文ハードコーディングにおいてインデント空白が邪魔になる状況はあるだろうか?パッと思いつく限りではログ出力だ。デバッグ時や、例外発生時にSQL文をログ出力したいことは良くある。そういう時、あまり深いインデントでヒアドキュメント記述していると、ログでSQL文がやたら右の方に出力されてしまうし、記述場所がバラバラだとSQL文によって出力位置が変化しまって読みづらい。
 ということで、もしもSQL文をヒアストリングでハードコーディングする場合は、まとめて定数フィールドとして定義しておくのが良いだろう。

    public class DataBaseAccess
    {
        const string SQL_HOGE = @"
            select *
            from
                HOGE_TABLE hoge,
                FUGA_TABLE fuga
            where
                hoge.ID = fuga.ID
        ";

        private void selectHogeFuga()
        {
            // db はなんかSqlDataSourceみたいなオブジェクト。超適当。定義もしてないw
            db.selectCommand(SQL_HOGE);
            db.select();
        }

    }

 こんな感じ?適当すぎてゴメンナサイ。
 フィールド定義であれば左インデントも最小限に抑えられるし、同じインデント階層で定義することで出力位置もバラバラにならない。まぁ、ヒアストリング使わなくても普通はそうやって書くと思うけどね…(StringBuilder派はReadOnly化してstaticブロックで書いたり?とかかもだけど)。
 SQLの記述法としては何が綺麗なやり方なのか模索中だったりする。外部リソースとしてXMLファイルかテキストファイルで書いておいて別途作った読み込みモジュールで読み込む…というのが好みだったりするけど、毎回それが必要とも限らない。まぁ、それは別のお話なので掘り下げないけど。

 ぶっちゃけこんな記法が出来たらいいのに!と思ったりもする。

string newHereStr = @" こんな書き方あったらいいな。
                    $ 特定の記号より左側の空白は消される。
                    $ 可読性も確保され、記述の面倒さもあんまりない.
                    ";

 この場合、$が特殊な文字になっていて、その左の空白が無視される記法という意味。まぁ、これを実現する文字列操作関数を自分で作ることは可能だが、コスト考えると微妙だし、ちょっと強引すぎる気もする。実際こんな実装を持つ言語もあるようだけど、便利に使われているのだろうか?

 以上。予定の3倍くらいの長さのエントリになってしまった…。

 
1件のコメント

投稿者: : 2011/04/24 投稿先 プログラム, C#

 

タグ: , , ,

C#でヒアドキュメント」への1件のフィードバック

  1. satoshi

    2017/03/09 at 11:37 午後

    行ごとに$前のスペースをカットするメソッドを作って
    ヒアドキュメントで文字列代入する前にそれに食わせればいいのではないでしょうか。

     

コメントを残す