[C#]usingとvarの組み合わせがウンチ

かなり古いエントリですが、やねうらおさんが以下の様なことを書いていました。

using (var sr = new StreamReader(path))
{
    var text = sr.ReadToEnd();
}
Console.WriteLine(text); // なんでここでtextにアクセス出来ないの?馬鹿なの?死ぬの?

C#のvarとtry~catchが糞すぎる

これは本当にそのとおりで、はじめは「うわっ、varってめっちゃ便利じゃん。マジすげえ」とか思ってたけど、しばらくPythonを打ってからC#に戻ってきたりすると愕然とする。こんなこともできんのか。たとえば以下のようなコードもコンパイルできない。

var readedData;
using (var sr = new StreamReader(path))
{
    readedData = new SomeDataClass(sr);
}
// 時間がかかる処理
readedData.Action();

なるべく早く資源を開放したい、だらだらとusingの中に処理を書きたくない、というのはまあ普通の考えだと思いますが、上記のようなコードはコンパイルできません。なぜならvarは宣言と同時に何か代入しないと怒られるからです。じゃあusingの中で宣言したらいいじゃん、って思うのだけど、当然、スコープがusingの中だけになるので当初の目的を達成できません。

だから以下のように書く。だせぇ。うぜぇ。

SomeDataClass readedData;
using (var sr = new StreamReader(path))
{
    readedData = new SomeDataClass(sr);
}
// 時間がかかる処理
readedData.Action();

まあこのくらいならまだマシなのだけど、varとtry-catchを混ぜた時はもっと面倒。詳しくは冒頭に紹介したやねさんのエントリを参照。

2件のコメント

  1. 匿名 より:

    こんにちは
    ご存知かもしれませんが
    ---
    var readedData = null as SomeDataClass;
    using (var sr = new StreamReader(path))
    {
    readedData = new SomeDataClass(sr);
    }
    // 時間がかかる処理
    readedData.Action();
    ---

    でできますよ。
    やねうらおさんのケースでも可能。

    ちなみに .NET 3.5からあります。
    型推論ちゃうやんというツッコミは残りますけどね。

    1. withpop より:

      こんにちは。コメントありがとうございます。
      asを使うというのは思いつきませんでした。

      仰るとおり、推論してないので結局
      SomeDataClass readedData;
      と宣言したほうが簡潔になっちゃうんですよね。

      そもそもC#の型推論が弱くて、メソッドの戻り値とかも推論してくれないので、
      こんなもんなのかなあ。と思って使うことにしています。
      とにかく文字を書きたくない、ってケースのために
      IronPythonがあるのかも。

ただいまコメントは受け付けていません。