【问题标题】:How do I overload the square-bracket operator in C#?如何在 C# 中重载方括号运算符?
【发布时间】:2010-09-22 05:20:41
【问题描述】:

例如,DataGridView 允许您这样做:

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

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

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

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

【问题讨论】:

    标签: c# collections operators operator-overloading


    【解决方案1】:
    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!
    

    Source of the information

    对于括号:

    public Object this[int index]
    {
    
    }
    

    但是

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

    来自MSDN

    【讨论】:

    • 可以重载,只要参数签名不同,就跟其他方法的重载限制一样
    • 可以,但不适用于我写的条件。它来自 MSDN。如果你不相信我,请查看来源
    • 对不起,如果我看错了你的帖子,但你指的是什么条件?
    • +1 方便的列表。仅供参考,链接已失效。 (4 年后,我知道了)
    • 我想补充一点,您现在可以在 C# 中覆盖隐式和显式类型转换。
    【解决方案2】:
    public class CustomCollection : List<Object>
    {
        public Object this[int index]
        {
            // ...
        }
    }
    

    【讨论】:

    • 实际上,这真的很危险 - 您现在有两个相互竞争的实现:任何类型为 List 或 IList 或 IList 等变量的人都不会执行您的自定义代码。跨度>
    • 同意 -- 如果不出意外,没有必要从 List 派生您的 CustomCollection,但我没有意识到这实际上很危险
    • 它仍然会执行自定义代码,不是吗?你声明什么变量类型并不重要——重要的是对象的类型。
    • 对 C# 多态性的友好提醒:这是因为基类没有将其实现声明为虚拟。如果它被声明为虚拟的,则在每种情况下都会调用自定义代码。
    • 此外,由于两个索引器都是非虚拟的,因此此代码会给您一个编译器警告。编译器会建议您使用 new 关键字限定自定义索引器。
    【解决方案3】:

    您可以找到操作方法here。 简而言之就是:

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

    如果您只需要一个 getter,也可以使用 answer below 中的语法(从 C# 6 开始)。

    【讨论】:

    • 一个小评论:根据你在做什么,你可能会发现这样做更合适:get { return base[i]; } 设置 { 基数 [i] = 值; }
    • 这不是运算符重载。它是索引器
    • 索引器,也可以是一元运算符。
    • 2019年应该选择一个新的答案,this one。太糟糕了,SO 没有处理过时答案的功能,因为新的答案还没有接近获得 350 多个赞成票,尽管它值得。
    • @mins 我包含了另一个答案的链接。
    【解决方案4】:

    那就是 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...
    • 就其实现方式而言,它是“Item”,但在 C# 术语中,它是“this”
    • 对,但我问“我一辈子都找不到关于索引/方括号运算符的文档”——我的意思是当你在 MSDN 中查找一个库类时,其中他们会告诉您有关运营商的信息吗?这就是为什么我对它抛出的内容做了最后一个“ETA”——文档错误
    【解决方案5】:

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

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

    【讨论】:

      【解决方案6】:

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

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

      【讨论】:

      • 首先,您的意思是 this[],而不是 this() - 但是,在列表 (IList/IList/List) 非常危险 - 并且可能导致“int index”和“int employeeId”版本之间的细微错误。两者仍然可以调用。
      • 事实上,我认为我上面输入的代码不会在不添加新语句或覆盖语句的情况下编译,因为存在 this[int] 的 List 实现。这样做的潜力是正确的,只是将其作为重载索引器的示例。
      【解决方案7】:

      对于 CLI C++(使用 /clr 编译),请参阅 this MSDN link

      简而言之,一个属性可以被命名为“default”:

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

      【讨论】:

        【解决方案8】:

        如果您使用的是 C# 6 或更高版本,则可以对 get-only 索引器使用表达式主体语法:

        public object this[int i] =&gt; this.InnerList[i];

        【讨论】:

          猜你喜欢
          • 2017-08-15
          • 1970-01-01
          • 2022-01-20
          • 2011-12-03
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多