C # несколько индексаторов - PullRequest
14 голосов
/ 10 января 2009

Возможно ли иметь что-то вроде следующего:

class C
{
    public Foo Foos[int i]
    {
        ...
    }

    public Bar Bars[int i]
    {
        ...
    }
}

Если нет, то каким образом я могу достичь этого? Я знаю, что мог бы создавать функции с именами getFoo (int i) и getBar (int i), но я надеялся сделать это со свойствами.

Ответы [ 7 ]

16 голосов
/ 31 октября 2009

Это из 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);  
        }
    }      
}
16 голосов
/ 10 января 2009

Нет в C #, нет.

Однако вы всегда можете вернуть коллекции из свойств следующим образом:

public IList<Foo> Foos
{
    get { return ...; }
}

public IList<Bar> Bars
{
    get { return ...; }
}

IList имеет индексатор, поэтому вы можете написать следующее:

C whatever = new C();
Foo myFoo = whatever.Foos[13];

В строках "возврат ...;" вы можете вернуть все, что реализует IList , но вы можете, что бы вернуть оболочку только для чтения вокруг вашей коллекции, см. метод AsReadOnly ().

5 голосов
/ 10 января 2009

Есть способ ... если вы определили 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];

То же самое применимо, даже если два индексатора возвращают разные типы ...

4 голосов
/ 26 января 2012

Попробуйте в моем классе IndexProperty включить несколько индексаторов в одном классе

http://www.codeproject.com/Tips/319825/Multiple-Indexers-in-Csharp

3 голосов
/ 10 января 2009

Если вы пытаетесь сделать что-то вроде этого:

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]);
0 голосов
/ 10 января 2009

Нет, вы не можете это сделать. Операторами преобразования являются только методы, которые могут иметь свои подписи, отличающиеся только типом возвращаемого значения. Индексаторы должны иметь разные типы входных параметров, чтобы компилировать их.

0 голосов
/ 10 января 2009

C # не имеет перегрузки типа возврата. Вы можете определить несколько индексаторов, если их входные параметры отличаются.

...