2016年10月1日土曜日

今週のモーニング

あらゐけいいちがモーニングでもあらゐけいいちでうれしい。楽しみが増えた。

2016年8月1日月曜日

IDisposable 汎用クラスの実装

ものすごく抽象的になりますが、おおよそこんなコードがありました。

var a = new A();
a.Do();

var b = new B(a);
b.Do();

// 後片付け
b.Cleanup();
a.Cleanup();

ところが実際には、A.DoにしろB.Doにしろ、省略しているそれ以外のところでも、例外がスローされる可能性がありました。コンストラクト済みのA、Bの両オブジェクトは、Cleanupメソッドを呼ぶ必要があり、例外がスローされた場合も正しく処理されるためには、以下のようにコードを修正する必要がありました。

A a = null;
B b = null;

try
{
  a = new A();
  a.Do();

  b = new B(a);
  b.Do();
}
finally
{
  if (b != null)
    b.Cleanup();

  if (a != null)
    a.Cleanup();
}

結果として、A、Bいずれも宣言と同時に初期化ができなくなり、finally句内の後片付けも、構築済みかどうかのチェックが必要になってしまいました。

実際、この手のコードはたまに見かけます。正しく書くとこうなってしまうケース。でも、正直カッコワルいよね。ちなみに、このケースならA,Bの両クラスがIDisposableを実装して、DisposeでCleanupできれば問題ないんだけど、そうもいかないケースも結構多いですよね。

で、考えてみたのが「それなら、IDisposableの汎用クラスを作ってしまえば良いんじゃないか」ということ。試しに作ってみたのは、こんなどシンプルなクラス。クラス名は「Disposeするヒト」なので、「Disposer」クラス。

public class Disposer : IDisposable
{
  private readonly Action disposer;

  public Disposer(Action disposer)
  {
    this.disposer = disposer;
  }

  public void Dispose()
  {
    disposer();
  }
}

これを作っておくことで、先のコードはこう変わります。

var a = new A();
using (new Disposer(() => a.Cleanup()))
{ 
  a.Do();

  var b = new B(a);
  using (new Disposer(() => b.Cleanup()))
  {
    b.Do();
  }
}

usingのスコープを抜けたときに行う処理を、あらかじめ定義しておくイメージでしょうか。ちなみに、using句でnewされたオブジェクトが特に参照されないのであれば、変数に代入しなくてもちゃんと動くんですね。初めて知った。

もう8月ですね...

ほとんど更新しないまんまもう8月。月日の経つのはほんと早い。

いや、真田丸も面白いし、相変わらず漫画もたくさん読んでるし、ポケモンGOも始めたしで、書くことないわけでもないんですが、やっぱり本筋のC#/LINQ的なネタがないと、他のことも書こうという気になかなかならず...。

ちょっとだけネタができたので、ぼちぼち行きます。

2016年1月20日水曜日

今週のマガジン

「AKB49」が完結しましたね。始まったときはイロモノかと持ったのですが、なかなかどうして面白かったです。

あとはやっぱり「ベイビーステップ」がやっぱり楽しい。今回のような試合じゃないけど、テニスプレイヤーとしての一面を見せてくれるような回があるのがとてもよいです。

2016年1月18日月曜日

「真田丸」が面白い!

おぉ。いつの間にか年が明けておりますね…。ごにょごにょ…。

…さて、今年の大河ドラマ「真田丸」が面白いです!すごく!

大河ドラマはどうしても、最初のほうは、時代の背景や主人公の特に幼少期のエピソードなどの説明が主になってしまい、最初の二か月ぐらいは我慢してみてると、そのうち面白くなってくる。というのがパターンでした。

が、今回はもう最初から面白い。

予想していたのは、長篠の戦いあたりがスタートで、信幸・信繁兄弟の幼少期から入ると思っていました。が、幼少期はぶっとばして、いつも通りの子役からなんてことはせず、武田家滅亡の直前からのスタートで、堺さんと大泉さんに14~5歳をやらせた。たぶん、正解だと思う。

その堺さんと大泉さん。始まる前は「逆じゃね?」と思ったけど、すごくしっくりくる。そんでなにより、おとーちゃんの草刈正雄。もーぴったりすぎ。(昔のNHKの「真田太平記」で幸村(信繁)役だったらしい。)

お話もすばらしい。わかりやすい。展開早くてだれない。そして大河なのにところどころに笑いを差し込んでくる。いーねー!

そして、過去の大河ドラマでよく不満に思っていたのは、戦闘などがあった時にその地理的な位置関係などの説明が少なく、なんでその結果になったのか、よくわからないことが多かった。

しかし、今回は非常にわかりやすい地図と共に背景を説明してくれるので、理解が早くて話に入りやすい。この地図がいい!(オープニングのタイトルロールで、「シブサワ・コウ」の名前を見たときはビビりました。)


ひとまず二話まで終わった時点では先が楽しみで仕方がないです。


…そして、Twitterの「#真田丸どうでしょう」に爆笑。

2015年11月5日木曜日

今週のモーニング

『ピアノの森』が最終回を迎えました。

連載開始から18年とのこと。ものすごい長期連載が大団円を迎えました。
最初の連載はアッパーズで、当時掲載誌で読んでました。アッパーズは好きだったなぁ。
長らく楽しませていただきました。最終回は、ありゃ泣くよ。

お疲れ様でした。次回作はどんなお話でしょうか。楽しみにしてます。

それと、『決してマネしないでください』が次回で最終回とのこと。これも楽しみだっただけに、正直もう少し続けてほしかったなぁ。

2015年10月22日木曜日

SJISのCSVファイルを各カラムの操作と条件による絞り込みを行い、UTF-8のCSVファイルを出力する処理をLINQで。(改)

もともとは「ラムダ式を利用したリファクタリングの例 その2」で扱った後、さらに「SJISのCSVファイルを各カラムの操作と条件による絞り込みを行い、UTF-8のCSVファイルを出力する処理をLINQで。」で修正版を示したネタです。改二ですな。

こんな要求に対する処理を書いていました。
  • Shift-JISのCSVファイルを入力し、UTF-8のCSVファイルを出力する。
  • 入力したCSVの各カラムは、固定長で前後に空白が入る可能性があり、その空白は除去して出力する。
  • 各行の先頭のカラムはIDになっていて、特定のIDのみ出力対象とする。
inFileが入力ファイルのパス、outFileが出力ファイルのパスとして、絞り込みの条件を「先頭カラムが奇数」とすると、以下のコードで拡張メソッドとか作らなくても要求が満たせてしまいますね。

File.WriteAllLines(
  outFile,
  File.ReadLines(inFile, Encoding.GetEncoding("shift-jis"))
    .Select(line => line.Split(','))
    .Where(items => int.Parse(items[0]) % 2 != 0)
    .Select(items => string.Join(",", items.Select(item => item.Trim()))));

  • inFileからShift-JISで各行を読み込み、
  • ',' で分割し、
  • 先頭カラムが奇数の行について、
  • 各カラムの前後の空白を除去した上で再度 ',' で結合し、
  • outFileに書き込む。

という処理になります。日本語とほぼ一対一にコードが対応してます。ちなみに、.net 2.0相当でコードを書くとこんな感じ。

var sb = new StringBuilder();
string line;

using (var sr = new StreamReader(inFile, Encoding.GetEncoding("shift-jis")))
using (var sw = new StreamWriter(outFile))
{
  while ((line = sr.ReadLine()) != null)
  {
    var items = line.Split(',');
    sb.Length = 0;

    if (int.Parse(items[0]) % 2 != 0)
    {
      foreach (var item in items)
      {
        sb.Append(item.Trim()).Append(',');
      }
      sw.WriteLine(sb.ToString(0, sb.Length - 1));
    }
  }
}

雲泥の差がありますねぇ…。