C# несколько индексаторов
Возможно ли иметь что-то вроде следующего:
class C
{
public Foo Foos[int i]
{
...
}
public Bar Bars[int i]
{
...
}
}
Если нет, то каким образом я могу достичь этого? Я знаю, что мог бы создавать функции с именами getFoo(int i) и getBar(int i), но я надеялся сделать это со свойствами.
8 ответов
Нет в C#, нет.
Однако вы всегда можете вернуть коллекции из свойств следующим образом:
public IList<Foo> Foos
{
get { return ...; }
}
public IList<Bar> Bars
{
get { return ...; }
}
IList
C whatever = new C();
Foo myFoo = whatever.Foos[13];
На строках "вернись...;" вы можете вернуть все, что реализует IList
Это из C# 3.0 spec
"Перегрузка индексаторов позволяет классу, структуре или интерфейсу объявлять несколько индексаторов при условии, что их сигнатуры уникальны в этом классе, структуре или интерфейсе".
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 новых типа, чтобы компилятор мог различать две разные сигнатуры...
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];
То же самое применимо, даже если два индексатора возвращают разные типы...
Попробуйте мой класс 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]);
Я считаю, что принятый ответ неверен. Это возможно, если вы будете использовать явную реализацию интерфейса:
class C
{
public IFooProvider Foos => this;
public IBarProvider Bars => this;
Foo IFooProvider.this[int i]
{
...
}
Bar IBarProvider.this[int i]
{
...
}
public interface IFooProvider
{
Foo this[int i] { get; set; }
}
public interface IBarProvider
{
Bar this[int i] { get; set; }
}
}
Тогда вы можете использовать его так, как хотели:
C c;
c.Foos[1] = new Foo();
c.Bars[0] = new Bar();
Нет, ты не можешь сделать это. Операторы преобразования являются только теми методами, у которых подписи могут отличаться только типом возвращаемого значения. Индексаторы должны иметь разные типы входных параметров, чтобы компилировать их.
C# не имеет перегрузки типа возврата. Вы можете определить несколько индексаторов, если их входные параметры отличаются.