トップ «前の日記(2006-02-03) 最新 次の日記(2006-02-05)» 編集

日々の破片

Subscribe with livedoor Reader
著作一覧

2006-02-04

_ 横浜ではないMS

「Dave Provert」(soutaroにっき)の講義の実際。

さらにリンク先の登さんのところがおもしろい(本当に雑談なのだけど)。Priusに乗りたがるところとか。

#今日の薀蓄。HALはHardware Adaptation Layerが正しい。(だからどうというわけでもないけど、MS Pressの公式の呼び方と実際に作ってるところで名前が違うという点。確かにあるな)

_ LINQ続き

今は資料が手元にあるので、セッションの内容を書いてみる(適当にこちらで再構成して、さらに省略してある)。

出発点

public class Foo {
    public Foo(string r, int z) { bar = r; baz = z; }
    string Bar;
    int Baz;
}
public class Foos {
    public static Foo[] GetItems() {
        return new Foo[] { new Foo("a", 0), new Foo("b", 1), new Foo("c", 2) };
    }
}
LINQは、SQL専用の構文ではなく、コレクションに対する統一した操作を提供するものだ。したがって、上のFoosを処理できなければならない。
var v = from foo in Foos.GetItems()
        where foo.baz > 0
        select new { foo.bar };
この結果としてvには
class ? {
    public ?(string s) { bar = s; }
    string bar;
}
?[] { new ?("b"), new ?("c") };
が入る。
したがって
foreach (var i in v) {
    System.Console.WriteLine(i.
と打つとインテリセンスがbarを表示する。
.NET Framework 2.0は変えないのだから、LINQの構文はオブジェクトに対するメソッド呼び出しに落とし込む必要がある。
var v = Foos.GetItems().Where(foo => foo.baz > 0).Select(foo => new { foo.bar, boo.baz});
ここで新たに加わった言語要素が、
  • varというローカル変数の型推論指定子
  • WhereSelectという外部メソッド(Foo[]がWhereを実装する必要があってはならないことは自明)をオブジェクトのメソッドルックアップの対象とする機構(拡張メソッド)
  • ラムダ式 (パラメータリスト=>ブロック本体)
  • new { 初期化指定 }という無名型とその初期化構文
実際には、ここに至るまでの検討も相当あったようだ。たとえば拡張メソッドという仕組みがなければ、すべてのクラスにWhereやSelectというメソッドを実装することを強制すれば良い。が、これは.NET Framework 2.0の既存クラスに影響を与えるし、そもそも無駄(代替手段があれば)。
次に
public static class Sequence
{
    public static IEnumerable<T> Where<T>(IEnumerable<T> source, Func predicate) { ... }
    ...
}
というユーティリティを作ってそれを直接呼ばせる方法。そうすれば
var v = Sequence.Select(Sequence.Where(Foos.GetItems(), foo => foo.baz > 0), foo => new { foo.bar, boo.baz});
というようにスタティックメソッドのネストを利用することができる。
この場合の問題点として、ヘルスバーグが挙げた理由は可読性の低さ(Selectの構文に対して「何だって?」)。

#でも、この展開はコンパイラがLINQの構文から自動的に行うのだから、それほど必然性は無いようにも思えるな、今、思い返すと。
ただし、もしLINQ構文を利用しないのであれば、引数そのものにはインテリセンスは効かないのに対して、Foos.GetItems().と打った時点でWhereを出すことができる拡張メソッドのほうがVisual Studioを前提とした場合には望ましいということはわかる。

拡張メソッド構文では上のSequenceの定義が次のように変わる。
public static class Sequence
{
    public static IEnumerable<T> Where<T>(this IEnumerable<T> source, Func<T, bool> predicate) { ... }
    ...
}
第1引数をthisで修飾すると、第1引数の型のメソッドルックアップテーブルにメソッドが追加される。
というのがさわりの部分だった。
本日のツッコミ(全2件) [ツッコミを入れる]
_ babie (2006-02-06 09:34)

「と打つとインテリセンスがbarを表示する。」で bar の code タグが閉じられていないので、以降全ての文字がcodeクオリティ(小さい)になっています。

_ arton (2006-02-06 10:06)

修正しました。どうもありがとう。


2003|06|07|08|09|10|11|12|
2004|01|02|03|04|05|06|07|08|09|10|11|12|
2005|01|02|03|04|05|06|07|08|09|10|11|12|
2006|01|02|03|04|05|06|07|08|09|10|11|12|
2007|01|02|03|04|05|06|07|08|09|10|11|12|
2008|01|02|03|04|05|06|07|08|09|10|11|12|
2009|01|02|03|04|05|06|07|08|09|10|11|12|
2010|01|02|03|04|05|06|07|08|09|10|11|12|
2011|01|02|03|04|05|06|07|08|09|10|11|12|
2012|01|02|03|04|05|06|07|08|09|10|11|12|
2013|01|02|03|04|05|06|07|08|09|10|11|12|
2014|01|02|03|04|05|06|07|08|09|10|11|12|
2015|01|02|03|04|05|06|07|08|09|10|11|12|
2016|01|02|03|04|05|06|07|08|09|10|11|12|
2017|01|02|03|04|05|06|07|08|09|10|11|12|
2018|01|02|03|04|05|06|07|08|09|10|11|12|
2019|01|02|03|04|05|06|07|08|09|10|

ジェズイットを見習え