またまた、またインデクサ

窓際プログラマーの独り言より

XmlReader(リンクではXmlTextReader)のインデクサがXMLの属性にアクセスするプロパティだというのは直感的では無い、という話。 全く以って同意する。

異論、反論はあると思うがC#のインデクサというのはインタフェース、ひいてはクラスを設計する際によほど考えた末にコーディング上有用である、と判断されたもの以外は不要、いやむしろ蛇足でしかない思うのだがどうだろう。

XmlReaderの場合、インデクサはXmlReaderが現在指しているXML要素の属性のコレクションにアクセスするプロパティであり以下のように使う。

using (XmlReader reader = XmlReader.Create(stream, setings))
{
  while (reader.Read())
  {
    〜
    if (reader.NodeType == XmlNodeType.Element)
    {
        if (reader.LocalName == "fooElement" )
        {
        〜
          string fooValue = reader[1];   
          string barValue = reader["bar"];
    }
  }
};

XmlReaderの使い方を知っているプログラマならなんてことないが初めてこのソースを見たプログラマはパーサへ配列のようにアクセスしている部分の意図を推測するのはひじょうに困難だろうと思う。同じプロパティと連想配列のようなコーディングをさせたいのであれば以下のように書けるほうがずっとましだと思う

using (XmlReader reader = XmlReader.Create(stream, setings))
{
  while (reader.Read())
  {
    〜
    if (reader.NodeType == XmlNodeType.Element)
    {
        if (reader.LocalName == "fooElement" )
        {
        〜
          string fooValue = reader.Attributes[1];   
          string barValue = reader.Attributes["bar"];
    }
  }
};

しかしそうはなっていないのである。(GetAttribute(〜)という直感的なメソッドは使える)。

.NETを使うようになってDelphiでは当たり前だったプロパティやインデクサが使えるようになって随分と便利になるなと思ったものだが正直なところインデクサの実装は時として非常に慎重にならざるを得ない程に難しい。特にプロパティの更新によりなんらかの副作用(プロパティの更新をきっかけにして動く別な処理)がある場合は尚更であり、悩む位ならば実装を提供しないほうが良いのではないかと思うほどだ。