補助関数:AddKeyValue

関数 AddKeyValue は、関数 Update の実現を補助するもので、辞書 self に要素対 o を登録します。

    internal static class DictOps {
public static bool AddKeyValue(IDictionary self, object o) {
IEnumerator i = Ops.GetEnumerator(o);
if (i.MoveNext()) {
object key = i.Current;
if (i.MoveNext()) {
object value = i.Current;
self[key] = value;
return !i.MoveNext();
}
}
return false;
}

メソッド AddKeyValue のヘッダーを見ると、リターン型が bool になっています。すると、次のような構造が見えてきます。

    bool AddKeyValue(...) {
...
self[key] = value; // 要素対を追加する
...
return false;
}

メソッド本体で要素対を追加できないと、false をリターン値とします。仕様では、2つの要素(キー/値)が指定されるはずです。ここには、次に示す典型的な C# のイディオムが記述してあります。


    IEnumerator i = Ops.GetEnumerator(o);
if (i.MoveNext()) { // 次のキー要素がある
object key = i.Current;
if (i.MoveNext()) { // 次の値要素がある
object value = i.Current;
self[key] = value; // 要素対を追加する

return !i.MoveNext();
}
}

インターフェース IEnumerator i で規定したプロトコルに従って、キー/値の順に、各要素 key/value を順に参照します。そして、インターフェース IDictionary self で規定したプロトコルに従って、要素対を設定します。最後に

    return !i.MoveNext();

とあるので、キー/値の次に、意味のない要素があると、false をリターン値とします。キー/値の他に要素がないと、true をリターン値とします。つまり、2つの要素(キー/値)が指定されたときだけ、その動作を保証します。


Previous〈3/3〉Next

インターフェース:IDictionaryEnumerator


if に続く条件式 dict != null が成立するなら、変数 dict によって参照される引数は、インターフェース IEnumerator で規定したプロトコルに従います。そこで、メソッド本体を見ると、次に示す典型的な C# のイディオムが記述してあります。

    IDictionaryEnumerator e = dict.GetEnumerator();
while (e.MoveNext()) {
self[DictOps.NullToObj(e.Key)] = e.Value;
}

インターフェース IDictionaryEnumerator で規定したプロトコルに従って、各要素 e を順に参照します。メソッド呼び出し dict.update の対象となるインスタンス self に対して、キー要素 e.Key と値要素 e.Value とを登録します。このとき(次に示す)補助関数 NullToObj を使うと、キー要素として無効な null の代わりに、有効な None がキー要素になります。
《参照》インターフェース IDictionaryEnumerator の詳細は、http://msdn.microsoft.com/en-us/library/system.collections.idictionaryenumerator.aspx を参照してください。□

補助関数:NullToObj

関数 NullToObj は、いくつかの関数の実現を補助するもので、必要なら、None に相当するオブジェクトをリターン値とします。

    internal static class DictOps {
public static object NullToObj(object o) {
if (o == null) return nullObject;
return o;
}

if に続く条件式 o == null が成立するなら、nullObject(None に相当する唯一のインスタンス Sigleton)をリターン値とします。それ以外は、与えられたままの引数をリターン値とします。これによって、有効な Python のオブジェクトが得られることを保証します。

インターフェース:IEnumerator

if に続く条件式 dict != null が成立しないなら、引数 b によって参照されるものは、汎用のインターフェース IEnumerator で規定したプロトコルに従ってアクセスします。そこで、メソッド本体を見ると、次に示す典型的な C# のイディオムが記述してあります。

    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++;
}

ここでは、引数 b からどのようにして IEnumerator が得られるか(how)は知らなくても、それを使ってなにをしたいか(what)を理解できれば、十分です。b の各要素を参照したいときに、Ops.GetEnumerator を利用するだけです。
局所変数 index は、エラーメッセージを補足する情報として、引数の位置を保持します。これによって、何番目の引数に問題があるかを明らかにします。
インターフェース IEnumerator で規定したプロトコルに従って、各要素 i を順に参照します。(次に示す)補助関数 AddKeyValue を使って、メソッド呼び出し dict.update の対象となるインスタンス self に対して、要素対 i.Current(キー:値)を追加します。ただし、要素対を追加できないときには、例外 Ops.ValueError を生成して、エラーメッセージを出力します。