如何在C#中重载方括号运算符?


254

例如,使用DataGridView,您可以执行以下操作:

DataGridView dgv = ...;
DataGridViewCell cell = dgv[1,5];

但是对于我来说,我找不到索引/方括号运算符的文档。他们怎么称呼它?在哪里实施?能扔吗?我如何在自己的课堂上做同样的事情?

ETA:感谢您提供所有快速解答。简要地说:相关文档在“项目”属性下;重载的方法是通过声明一个类似的属性public object this[int x, int y]{ get{...}; set{...} }; 至少根据文档,DataGridView的索引器不会抛出。它没有提到如果您提供无效的坐标会发生什么。

再次ETA:好的,即使文档中没有提及它(顽皮的Microsoft!),事实证明,如果为DataGridView的索引器提供了无效的坐标,则实际上它会抛出ArgumentOutOfRangeException。公平警告。

Answers:


374

您可以在这里找到操作方法。简而言之是:

public object this[int i]
{
    get { return InnerList[i]; }
    set { InnerList[i] = value; }
}

如果您只需要一个吸气剂,那么也可以使用以下答案中的语法(从C#6开始)。


9
一条小评论:根据您的工作,您可能会发现这样做更合适:get {return base [i]; }设置{base [i] =值;}
MikeBaz-MSFT 2012年

7
这不是运算符重载。它是索引器
析构

5
索引器也可以是一元运算符。
alan2here

1
在2019年,一个新的答案应选,这一个。太糟糕了,SO没有处理过时的答案的功能,因为新的答案虽然有应得的机会,但尚无法获得350多个投票。
分钟

@mins我提供了另一个答案的链接。
鲁本

41

那将是item属性:http : //msdn.microsoft.com/en-us/library/0ebtbkkc.aspx

也许这样的事情会工作:

public T Item[int index, int y]
{ 
    //Then do whatever you need to return/set here.
    get; set; 
}

非常感谢!如果可以设置两个答案,我也会添加您的答案-没人知道要在文档中查找Item…
Coderer

5
就实现方式而言,它是“项”,但在C#中,它是“此”
Marc Gravell

1
是的,但是我问“我一生中找不到索引/方括号运算符的文档”-我的意思是当您在MSDN中查找库类时,它们在哪里告诉您有关运算符的信息?这就是为什么我对它抛出的内容进行了最后的“ ETA”-文档是错误的
编码员

26
Operators                           Overloadability

+, -, *, /, %, &, |, <<, >>         All C# binary operators can be overloaded.

+, -, !,  ~, ++, --, true, false    All C# unary operators can be overloaded.

==, !=, <, >, <= , >=               All relational operators can be overloaded, 
                                    but only as pairs.

&&, ||                  They can't be overloaded

() (Conversion operator)        They can't be overloaded

+=, -=, *=, /=, %=                  These compound assignment operators can be 
                                    overloaded. But in C#, these operators are
                                    automatically overloaded when the respective
                                    binary operator is overloaded.

=, . , ?:, ->, new, is, as, sizeof  These operators can't be overloaded

    [ ]                             Can be overloaded but not always!

信息来源

对于支架:

public Object this[int index]
{

}

数组索引运算符不能重载;但是,类型可以定义索引器,带有一个或多个参数的属性。索引器参数与数组索引一样,用方括号括起来,但是可以将索引器参数声明为任何类型(与数组索引不同,数组索引必须是整数)。

MSDN


是的,只要参数签名不同,就可以重载,就像任何其他方法的重载限制一样
Charles Bretana

可以,但不能满足我写的条件。它来自MSDN。如果您不相信我,请查看源代码
Patrick Desjardins,

1
对不起,如果我看错了您的帖子,但是您指的是什么情况?
Charles Bretana

便捷列表+1。仅供参考,链接无效。(4年后,我知道)
Mixxiphoid

我想补充一点,您现在可以覆盖C#中的隐式和显式类型转换。
Felype

9

如果您使用的是C#6或更高版本,则可以对仅获取索引器使用表达式绑定语法:

public object this[int i] => this.InnerList[i];


6
public class CustomCollection : List<Object>
{
    public Object this[int index]
    {
        // ...
    }
}

5
实际上,这确实很危险-您现在有两个相互竞争的实现:变量类型为List <T>或IList <T>或IList等的任何人都不会执行您的自定义代码。
马克·格雷韦尔

1
同意-如果没有其他要求,则不必从List派生CustomCollection,但我没有意识到这实际上很危险
Coderer

它仍然会执行自定义代码,不是吗?声明什么变量类型都没有关系-重要的是对象的类型。
izb 2010年

1
友好提醒C#多态性:发生这种情况是因为基类没有将其实现声明为虚拟的。如果将其声明为虚拟的,则在每种情况下都将调用自定义代码。
almulo

1
另外,由于两个索引器都是非虚拟的,因此此代码还会向您发出编译器警告。编译器将建议您使用new关键字限定自定义索引器。
amoss,2016年

4

对于CLI C ++(与/ clr编译),请参见此MSDN链接

简而言之,可以将属性命名为“默认”:

ref class Class
{
 public:
  property System::String^ default[int i]
  {
    System::String^ get(int i) { return "hello world"; }
  }
};

2

这是一个从内部List对象返回值的示例。应该给你的主意。

  public object this[int index]
  {
     get { return ( List[index] ); }
     set { List[index] = value; }
  }

1

如果您的意思是数组索引器,则可以通过编写索引器属性来重载该索引。并且,只要每个索引器具有不同的参数签名,就可以重载(写入任意数量的索引器)属性。

public class EmployeeCollection: List<Employee>
{
    public Employee this[int employeeId]
    {   
        get 
        { 
            foreach(var emp in this)
            {
                if (emp.EmployeeId == employeeId)
                    return emp;
            }

            return null;
        }
    }

    public Employee this[string employeeName]
    {   
        get 
        { 
            foreach(var emp in this)
            {
                if (emp.Name == employeeName)
                    return emp;
            }

            return null;
        }
    }
}

2
首先,您的意思是this []而不是this()-但是,在列表(IList / IList <T> / List <T>)上提供自定义(但不同)this [int]是非常危险的-并且可能会导致“ int index”和“ int employeeId”版本之间的细微错误。两者仍然可以调用。
马克·格拉韦尔

实际上,我不认为正是由于this [int]的List <T>实现的存在,我在上面输入的代码不会在不添加新语句或覆盖语句的情况下进行编译。您这样做的潜力是正确的,只是将其作为重载索引器的示例。
Charles Bretana
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.