次のようなものを持つことは可能ですか?
class C
{
public Foo Foos[int i]
{
...
}
public Bar Bars[int i]
{
...
}
}
そうでない場合、これを達成する方法はいくつかありますか? getFoo(int i) および getBar(int i) という関数を作成できることはわかっていますが、これをプロパティで行うことを望んでいました。
次のようなものを持つことは可能ですか?
class C
{
public Foo Foos[int i]
{
...
}
public Bar Bars[int i]
{
...
}
}
そうでない場合、これを達成する方法はいくつかありますか? getFoo(int i) および getBar(int i) という関数を作成できることはわかっていますが、これをプロパティで行うことを望んでいました。
C# ではありません。
ただし、次のように、いつでもプロパティからコレクションを返すことができます。
public IList<Foo> Foos
{
get { return ...; }
}
public IList<Bar> Bars
{
get { return ...; }
}
IList<T> にはインデクサーがあるため、次のように記述できます。
C whatever = new C();
Foo myFoo = whatever.Foos[13];
「return ...;」の行で IList<T> を実装するものは何でも返すことができますが、コレクションの読み取り専用ラッパーを返すものもあるかもしれません。AsReadOnly() メソッドを参照してください。
これはC# 3.0仕様から
「インデクサーのオーバーロードにより、クラス、構造体、またはインターフェイスで複数のインデクサーを宣言できます。ただし、それらのシグネチャがそのクラス、構造体、またはインターフェイス内で一意である場合に限ります。」
public class MultiIndexer : List<string>
{
public string this[int i]
{
get{
return this[i];
}
}
public string this[string pValue]
{
get
{
//Just to demonstrate
return this.Find(x => x == pValue);
}
}
}
方法があります.. 2 つの新しい型を定義して、コンパイラが 2 つの異なるシグネチャを区別できるようにする場合...
public struct EmployeeId
{
public int val;
public EmployeeId(int employeeId) { val = employeeId; }
}
public struct HRId
{
public int val;
public HRId(int hrId) { val = hrId; }
}
public class Employee
{
public int EmployeeId;
public int HrId;
// other stuff
}
public class Employees: Collection<Employee>
{
public Employee this[EmployeeId employeeId]
{
get
{
foreach (Employee emp in this)
if (emp.EmployeeId == employeeId.val)
return emp;
return null;
}
}
public Employee this[HRId hrId]
{
get
{
foreach (Employee emp in this)
if (emp.HRId == hrId.val)
return emp;
return null;
}
}
// (or using new C#6+ "expression-body" syntax)
public Employee this[EmployeeId empId] =>
this.FirstorDefault(e=>e.EmployeeId == empId .val;
public Employee this[HRId hrId] =>
this.FirstorDefault(e=>e.EmployeeId == hrId.val;
}
それを呼び出すには、次のように書く必要があります。
Employee Bob = MyEmployeeCollection[new EmployeeID(34)];
そして、暗黙の変換演算子を書いた場合:
public static implicit operator EmployeeID(int x)
{ return new EmployeeID(x); }
それを使用するためにそれを行う必要さえありません。次のように書くだけです。
Employee Bob = MyEmployeeCollection[34];
2 つのインデクサーが異なる型を返す場合でも、同じことが当てはまります...
IndexPropertyクラスを試して、同じクラスで複数のインデクサーを有効にします
http://www.codeproject.com/Tips/319825/Multiple-Indexers-in-Csharp
このようなことをしようとしている場合:
var myClass = new MyClass();
Console.WriteLine(myClass.Foos[0]);
Console.WriteLine(myClass.Bars[0]);
次に、FooクラスとBarクラス自体にインデクサーを定義する必要があります。つまり、すべてのFooオブジェクトをFoos内に配置し、Foosを直接インデックス付けをサポートするタイプインスタンスにします。
メンバープロパティに配列を使用する方法を示すには(既にインデクサーをサポートしているため)。
public class C {
private string[] foos = new string[] { "foo1", "foo2", "foo3" };
private string[] bars = new string[] { "bar1", "bar2", "bar3" };
public string[] Foos { get { return foos; } }
public string[] Bars { get { return bars; } }
}
あなたが言うことを可能にするでしょう:
C myThing = new C();
Console.WriteLine(myThing.Foos[1]);
Console.WriteLine(myThing.Bars[2]);
C#にはリターン型のオーバーロードはありません。入力パラメーターが異なる場合は、複数のインデクサーを定義できます。
いいえ、できません。シグニチャを持つことができるメソッドのみが、戻りタイプによってのみ異なります。これは変換演算子です。インデクサーは、コンパイルするために異なる入力パラメータータイプを持っている必要があります。