インスタンスの型情報

前半には、次に示す典型的な C# のイディオムが記述してあります。

    string s;
Type t = obj.GetType();
if (t == typeof(T1)) {
s = "t1";
} else if (t == typeof(T2)) {
s = "t2";
} else {
s = ... // その他
}

このイディオムに照らし合わせて見ると、与えられた引数 set の型に合わせて、その型名を表わす文字列 "set"/"frozenset" を設定しているのが分かります。
《参照》式 typeof:詳細は C# idioms を参照してください。

    setTypeStr = Ops.GetDynamicType(set).Name;

ここでは、引数 set からどのようにして型の情報が得られるか(how)は知らなくても、それを使ってなにをしたいか(what)を理解できれば、十分です。インスタンスの型を実行時に知りたいときに、Ops.GetDynamicType を利用するだけです。

インスタンスの文字列表現

リターン値を得るために、変数 sb が作業領域 StringBuilder を保持します。StringBuilder を使うと、文字列を編集(追加/削除/置換/挿入)したいときに便利です。すると、次のような構造が見えてきます。

    StringBuilder sb = new StringBuilder();
... sb.Append("...") ... // 文字列を末尾に追加する
return sb.ToString();

メソッド StringBuilder.Append を利用して、作業領域 sb の末尾に文字列を追加しながら、最後に、メソッド StringBuilder.ToString を利用して、リターン値となる文字列を得ているのが分かります。
《参照》クラス StringBuilder:詳細は C# idioms を参照してください。

要素を含まないときに

要素を含まないときには、括弧 ([]) で括るだけです。

    sb.Append("([");
...
foreach (object o in items) {
...
}
sb.Append("])");

対象となる IEnumerable items が、要素を含まないときには、foreach ループの本体を実行しません。そのため、作業領域 sb には、括弧 "([])" だけを追加します。

要素を区切るときに

要素を含まないか、1つだけ含むときには、カンマ「,」で区切る必要はありません。そのため、foreach ループでは、少し工夫が必要です。すると、次のような構造が見えてきます。

    string comma = "";
foreach (...) {
sb.Append(comma);
...
comma = ", ";
}

変数 comma の初期値は "" です。すると、foreach ループでは(最初の要素だけ)作業領域 sb の末尾に、空文字列 "" を追加します。そこで、変数 comma には、値 ", " を設定します。そして(次の要素から)作業領域 sb の末尾に、カンマ ", " を追加します。つまり、第2要素以降はつねに、各要素をカンマ「,」で区切ります。さらに、各要素を追加するには、次のようにします。

    sb.Append(Ops.Repr(o));

ここでは、引数 o からどのようにして文字列表現が得られるか(how)は知らなくても、それを使ってなにをしたいか(what)を理解できれば、十分です。インスタンスの文字列表現が欲しいときに、Ops.Repr を利用するだけです。


Previous|3/3|Next

ソースコード:SetHelpers.SetToString()

静的クラス SetHelpers では、クラス SetCollection/FrozenSetCollection で共有するメソッドを支援する、補助的な処理群(Helpers)を実現します。

    /// 
/// Contains common set functionality between set and forzenSet
///

static class SetHelpers {
public static string SetToString(object set, IEnumerable items) {
string setTypeStr;
Type setType = set.GetType();
if (setType == typeof(SetCollection)) {
setTypeStr = "set";
} else if (setType == typeof(FrozenSetCollection)) {
setTypeStr = "frozenset";
} else {
setTypeStr = Ops.GetDynamicType(set).Name;
}
StringBuilder sb = new StringBuilder();
sb.Append(setTypeStr);
sb.Append("([");
string comma = "";
foreach (object o in items) {
sb.Append(comma);
sb.Append(Ops.Repr(o));
comma = ", ";
}
sb.Append("])");

return sb.ToString();
}

これらのメソッドは static 宣言してあり、メソッド呼び出しの対象となるインスタンス自身(実引数 this)が、仮引数 set になります。つまり、static 宣言することで、一連のメソッドを「関数」として再定義するのです。

イディオム:StringBuilder

静的メソッド SetToString の本体は、2つの処理(前半/後半)に大別できます。

    public static string SetToString(object set, IEnumerable items) {
string setTypeStr;
...
StringBuilder sb = new StringBuilder();
...
}

前半では、与えられた引数から型の名前 setTypeStr を得て、後半では、それをもとにインスタンスに固有の文字列表現 sb を生成しています。