以前のεπιστημηさんのVB嫌い[2]というエントリーで
VBの引数付きプロパティとC#のインデクサを比較する話がありました。
Delphiにも配列プロパティというのがありまして、VBの引数付きプロパティと
同じような使い方ができます。(のはず。VB知らないので間違ってたらご指摘ください。)
type
  TAnimals = class(TObject)
  private
    function GetDog(Index: Integer): TDog;
    procedure SetDog(Index: Integer; Value: TDog);
    function GetCat(Index: String): TCat;
  public
    //ReadWriteプロパティ
    property Dogs[Index: Integer]: TDog read GetDog write SetDog;
    //ReadOnlyプロパティ
    property Cats[Index: String]: TCat read GetCat;
  end;
C#のインデクサと比較しての便利さは、やはりgetterとsetterのメソッドを定義するだけで
使えるところ。
そこで、C#2.0のジェネリックを使って、以下のようなユーティリティクラスを作ってみました。
public delegate V ArrayProperty1Get<V, K1>(K1 key1);
public delegate void ArrayProperty1Set<V, K1>(K1 key1, V value); 
public class ReadOnlyArrayProperty1<V, K1>
{
  public ReadOnlyArrayProperty1(
    ArrayProperty1Get<V, K1> getMethod)
  {
    this.getMethod = getMethod;
  }
  private ArrayProperty1Get<V, K1> getMethod;
  public V this[K1 key1]
  {
    get
    {
      return getMethod(key1);
    }
  }
}
public class ReadWriteArrayProperty1<V, K1>
{
  public ReadWriteArrayProperty1(
    ArrayProperty1Get<V, K1> getMethod,
    ArrayProperty1Set<V, K1> setMethod)
  {
    this.getMethod = getMethod;
    this.setMethod = setMethod;
  }
  private ArrayProperty1Get<V, K1> getMethod;
  private ArrayProperty1Set<V, K1> setMethod;
  public V this[K1 key1]
  {
    get
    {
      return getMethod(key1);
    }
    set
    {
      setMethod(key1, value);
    }
  }
}
これを使うと
public class Animals
{
  public Animals()
  {
    Dogs = new ReadWriteArrayProperty1<Dog, int>(GetDog, SetDog);
    Cats = new ReadOnlyArrayProperty1<Cat, string>(GetCat);
  } 
  private Dog GetDog(int index)
  {
    //
  }
  private void SetDog(int index, Dog value)
  {
    //
  }
  private Cat GetCat(string index)
  {
    //
  }
  public ReadWriteArrayProperty1<Dog, int> Dogs;
  public ReadOnlyArrayProperty1<Cat, string> Cats;
}
class Program
{
  static void Main(string[] args)
  {
    Animals animals = new Animals();
    animals.Dogs[0] = new Dog("パトラッシュ");
    animals.Dogs[1] = new Dog("ラッシー");
    animals.Cats["ABC"] = new Cat("たま"); //コンパイルエラー
  }
}
みたいなことができます。
「インデクスが2つ以上ある場合はど~するんや」と突っ込まれそうですが
その場合はK2、K3、…と型パラメータを増やしたバージョンを追加します。
私の経験上、インデクスが4つ以上もあるような配列プロパティには、自社開発の
アプリも含めて出合った記憶がありません。