ソースコード:DictOps.Update(IDictionary<>, object)

内部クラス DictOps では、クラス Dict で規定するメソッドに対する、実質的な処理群(Ops)を実現します。これらのメソッドを static 宣言することで「関数」として再定義します。また、メソッド呼び出しの対象となるインスタンス(実引数 this)が、ここでの仮引数 self になります。

    internal static class DictOps {
public static void Update(IDictionary self, object b) {
object keysFunc;
IDictionary dict = b as IDictionary;
if (dict != null) {
IDictionaryEnumerator e = dict.GetEnumerator();
while (e.MoveNext()) {
self[DictOps.NullToObj(e.Key)] = e.Value;
}
} else if (Ops.TryGetAttr(b, SymbolTable.Keys, out keysFunc)) {
// user defined dictionary
IEnumerator i = Ops.GetEnumerator(Ops.Call(keysFunc));
while (i.MoveNext()) {
self[DictOps.NullToObj(i.Current)] = Ops.GetIndex(b, i.Current);
}
} else {
// list of lists (key/value pairs), list of tuples,
// tuple of tuples, etc...
IEnumerator i = Ops.GetEnumerator(b);
int index = 0;
while (i.MoveNext()) {
if (!AddKeyValue(self, i.Current)) {
throw Ops.ValueError("dictionary update sequence element #{0} has bad length; 2 is required", index);
}
index++;
}
}
}

静的メソッド Update では、引数 b が、インターフェース IDictionary の規定に従うかどうかで、後の処理を振り分けます。すると、次のような構造が見えてきます。

    IDictionary dict = b as IDictionary;
if (dict != null) { // IDictionary の規定に従う
...
} else if (...) {
// user defined dictionary
...
} else {
// list of lists (key/value pairs), list of tuples,
// tuple of tuples, etc...
...
}

if に続く条件式 dict != null が成立するなら、インターフェース IDictionary で規定したプロトコルに従って、dict を処理します。それ以外は、工夫が必要です。2番目の if ブロックについては、別の記事「利用者定義の辞書を扱う」で解説するので、ここでは割愛します。


Previous〈2/3〉Next