16

是否有可能有以下内容:

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

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

如果没有,那么我可以通过哪些方式实现这一目标?我知道我可以制作名为 getFoo(int i) 和 getBar(int i) 的函数,但我希望用属性来做到这一点。

4

8 回答 8

21

不在 C# 中,不。

但是,您始终可以从属性中返回集合,如下所示:

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

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

IList<T> 有一个索引器,因此您可以编写以下内容:

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

在“返回...;”行 你可以返回任何实现 IList<T> 的东西,但你可能会在你的集合周围返回一个只读包装器,请参阅 AsReadOnly() 方法。

于 2009-01-10T17:10:03.940 回答
18

这来自 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);  
        }
    }      
}
于 2009-10-30T21:15:58.803 回答
6

有一种方法..如果您定义两种新类型来让编译器区分两个不同的签名...

  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];

即使两个索引器返回不同的类型,同样的事情也适用......

于 2009-01-10T17:49:26.077 回答
4

尝试我的 IndexProperty 类以启用同一类中的多个索引器

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

于 2012-01-25T22:04:06.973 回答
3

如果您尝试执行以下操作:

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]);
于 2009-01-10T17:13:23.277 回答
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();
于 2021-04-16T19:50:51.953 回答
0

C# 没有返回类型重载。如果输入参数不同,您可以定义多个索引器。

于 2009-01-10T17:24:05.113 回答
0

不,你不能这样做。只有其签名仅因返回类型而异的方法才是转换运算符。索引器必须具有不同的输入参数类型才能编译。

于 2009-01-10T17:32:34.347 回答