C# 多个索引器

发布于 2024-07-11 09:12:20 字数 255 浏览 12 评论 0原文

是否可能有类似以下内容:

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

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

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

Is it possible to have something like the following:

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

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

If not, then are what are some of the ways I can achieve this? I know I could make functions called getFoo(int i) and getBar(int i) but I was hoping to do this with properties.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

花海 2024-07-18 09:12:20

不是在 C# 中,不是。

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

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

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

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

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

在“return ...;”行上 您可以返回任何实现 IList的内容,但您可能会返回集合的只读包装器,请参阅 AsReadOnly() 方法。

Not in C#, no.

However, you can always return collections from properties, as follows:

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

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

IList<T> has an indexer, so you can write the following:

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

On the lines "return ...;" you can return whatever implements IList<T>, but you might what to return a read-only wrapper around your collection, see AsReadOnly() method.

你的心境我的脸 2024-07-18 09:12:20

这来自 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);  
        }
    }      
}

This from C# 3.0 spec

"Overloading of indexers permits a class, struct, or interface to declare multiple indexers, provided their signatures are unique within that class, struct, or interface."

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);  
        }
    }      
}
梦回梦里 2024-07-18 09:12:20

有一种方法..如果你定义了 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];

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

There IS a way.. if you define 2 new types to alow the compiler to distinguish the two different signatures...

  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;

  }

Then to call it you would have to write:

Employee Bob = MyEmployeeCollection[new EmployeeID(34)];

And if you wrote an implicit conversion operator:

public static implicit operator EmployeeID(int x)
{ return new EmployeeID(x); }

then you wouldn't even have to do that to use it, you could just write:

Employee Bob = MyEmployeeCollection[34];

Same thing applies even if the two indexers return different types...

海之角 2024-07-18 09:12:20

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

< a href="http://www.codeproject.com/Tips/319825/Multiple-Indexers-in-Csharp" rel="nofollow">http://www.codeproject.com/Tips/319825/Multiple-Indexers- in-Csharp

乞讨 2024-07-18 09:12:20

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

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

If you're trying to do something like this:

var myClass = new MyClass();

Console.WriteLine(myClass.Foos[0]);
Console.WriteLine(myClass.Bars[0]);

then you need to define the indexers on the Foo and Bar classes themselves - i.e. put all the Foo objects inside Foos, and make Foos a type instance that supports indexing directly.

To demonstrate using arrays for the member properties (since they already support indexers):

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

would allow you to say:

 C myThing = new C();
 Console.WriteLine(myThing.Foos[1]);
 Console.WriteLine(myThing.Bars[2]);
十年不长 2024-07-18 09:12:20

我相信接受的答案是错误的。 如果您使用显式接口实现,这是可能的:

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();

I believe the accepted answer is wrong. It is possible if you will use explicit interface implementation:

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

Then you can use it exactly like you wanted:

C c;
c.Foos[1] = new Foo();
c.Bars[0] = new Bar();
薔薇婲 2024-07-18 09:12:20

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

C# doesn't have return type overloading. You can define multiple indexers if their input parameters are different.

诠释孤独 2024-07-18 09:12:20

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

No you cant do it. Only methods that can have their signatures differ only by return type are conversion operators. Indexers must have different input parameter types to get it to compile.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文