【问题标题】:When should you use C# indexers?什么时候应该使用 C# 索引器?
【发布时间】:2011-03-19 21:59:54
【问题描述】:

我想更多地使用索引器,但我不确定何时使用它们。我在网上找到的都是使用 MyClassIndexerClass 等类的示例。

在有学生和教师的学校系统中,每个教师都有一个他们负责的学生列表 - 在这种情况下是否需要索引器?为简单起见:每个学生只能属于一位教师。

【问题讨论】:

    标签: c# indexer


    【解决方案1】:

    索引器是一个高度专业化的属性,它允许类(或结构)的实例像数组一样被索引(属性可以是静态的,但索引器不能)。

    为什么要使用索引器:
    - 类本身不是一个新的数据结构,而是一个数据结构。
    - 简化语法 - 语法糖

    何时使用:
    - 如果您的类需要其实例的列表(/数组)(示例 1)
    - 如果你的类代表与你的类直接相关的值的列表(/数组)(示例 2)

    示例 1:

    public class Person{
        public string Name{get; set;}
    
        private Person[] _backingStore;
        public Person this[int index]
        {
            get{
                return _backingStore[index];
            }
            set{
                _backingStore[index] = value;
            }
        }
    }
    
    Person p = new Person();
    p[0] = new Person(){Name = "Hassan"};
    p[1] = new Person(){Name = "John Skeet"};    
    

    示例 2:

    class TempratureRecord{
        private float[] temps = new float[10] { 56.2F, 56.7F, 56.5F, 56.9F, 58.8F, 61.3F, 56.5F, 56.9F, 58.8F, 61.3F};
    
        public int Length{
            get { return temps.Length; }
        }
    
        public float this[int index]
        {
            get{
                return temps[index];
            }
            set{
                temps[index] = value;
            }
        }
    }
    

    【讨论】:

      【解决方案2】:

      这是我创建的视频http://www.youtube.com/watch?v=HdtEQqu0yOY,下面是关于相同内容的详细说明。

      索引器有助于使用简化的接口在类中访问包含的集合。它是一种语法糖。

      例如,假设您有一个客户类,其中包含地址集合。现在假设我们想通过“Pincode”和“PhoneNumber”获取地址集合。因此,合乎逻辑的步骤是创建两个重载函数,一个使用“PhoneNumber”获取,另一个使用“PinCode”获取。您可以在下面的代码中看到我们定义了两个函数。

      Customer Customers = new Customer();
      Customers.getAddress(1001);
      Customers.getAddress("9090");
      

      如果你使用索引器,你可以用下面的代码来简化上面的代码。

      Customer Customers = new Customer();
      Address o = Customers[10001];
      o = Customers["4320948"];
      

      干杯。

      【讨论】:

        【解决方案3】:

        如果类表示对象的列表、集合或数组,则通常使用索引器。在您的情况下,您可以提供一个索引器来为教师的学生提供基于索引的访问。

        【讨论】:

        • +1 详细说明使索引器有意义的基于集合的方面,但提供教师\学生示例有点“为了它”。我不会认为作为索引类型概念的好的 API 会渗透到对象模型中。
        • 但也许只有老师/包含/学生,并且有一些重要的自然唯一键或分组?否则,教师可能只是将集合作为属性或方法返回类型。即teacher.Students["Jones"].FirstOrDefault() 使用Students Lookup 属性的索引器
        • @uosɐſ 那位先生是一个糟糕的 API,证明了我的观点。只暴露 IEnumerable 然后只针对它运行 Linq 有什么问题?
        • 我同意你的看法。我的帖子没有回复您的帖子,您在我还在写作时发布了 :-) 也就是说,我的 Students 属性是 IEnumerable -(必须,不能将命名索引作为单个类定义的一部分)
        【解决方案4】:

        随机顺序访问

        如果您的数据通常是按顺序访问的,您将使用枚举器。

        另一方面,索引器可用于直接访问特定元素,没有特定顺序。

        这当然假设你知道你想要的元素的索引。例如,组合框一直支持两个值:显示给用户的字符串和属于它的 id。您可以使用组合框中所选项目的 id 直接访问您的集合的索引,而不必搜索集合。

        C# 中索引器的好处是您可以重载它们,因此您可以通过不同类型的键访问项目。

        【讨论】:

          【解决方案5】:

          在您的情况下使用的索引器是 TeachersClass 类,它将封装学生(集合)和当前教师。虽然您可以通过公开学生列表来做同样的事情,但它确实向您展示了一个示例。

          这是一个代码示例:

          public class TeachersClass
              {
                  private List<Student> _students;
          
                  public TeachersClass(Teacher currentTeacher, List<Student> students)
                  {
                      CurrentTeacher = currentTeacher;
                      _students = students;
                  }
          
                  public Teacher CurrentTeacher { get; set; }
          
                  public Student this[int studentID]
                  {
                      get
                      {
                          return (from s in _students
                                  where s.Id = studentID
                                  select s).First();
                      }
                  }   
              }
          

          【讨论】:

            【解决方案6】:

            简单的答案(如上所述)是当类表示/包含项目的集合时,索引器将返回集合的元素。

            public Student this[int index] { ..
            

            在更高级的情况下,您可以使用类创建默认行为并使其看起来有点像委托,尤其是当类表示映射或进程时。例如一个计算冰箱中啤酒冷却速度的类:

            不用打字

            temperature = coorsLight.CalculateFutureTemperature(time);
            

            你可以放心

            temperature = coorsLight[time];
            

            如果类的预期行为(和意图)是返回一个值。

            【讨论】:

              【解决方案7】:

              索引器是一种从集合(例如数组或集合)中选择元素的方法。虽然我部分同意 Ian Davis,但我认为索引器代表的不仅仅是公共 API 润色。

              索引器是访问数组的主要方法,而 .NET BCL 中表示集合的大多数主要类都实现了索引器,大概是为了在处理聚合其他类型的类型时提供一种通用体验。

              因为索引器是许多 BCL 集合类型接口的标准部分,并且由于这些类型被大量使用,随着开发人员将 .NET 作为一个平台学习,建议创建集合可以使用某种类型的索引器进行访问。

              如果您的类型的界面符合开发人员的期望,那么该类型将变得更易于使用,因为开发人员无需思考。无论所讨论的开发人员是在您的组织内部还是在野外,这都是正确的。

              当然,在某些情况下使用索引器是没有意义的,如果是这样,那么就不要实现索引器。

              【讨论】:

                【解决方案8】:

                索引器允许类或结构的实例像数组一样被索引。索引器类似于属性,只是它们的访问器带有参数。

                索引器使对象能够以类似于数组的方式被索引。

                    // C#: INDEXER 
                using System; 
                using System.Collections; 
                
                class MyClass 
                { 
                    private string []data = new string[5]; 
                    public string this [int index] 
                    { 
                       get 
                       { 
                           return data[index]; 
                       } 
                       set 
                       { 
                           data[index] = value; 
                       } 
                    } 
                }
                
                class MyClient 
                { 
                   public static void Main() 
                   { 
                      MyClass mc = new MyClass(); 
                      mc[0] = "Rajesh"; 
                      mc[1] = "A3-126"; 
                      mc[2] = "Snehadara"; 
                      mc[3] = "Irla"; 
                      mc[4] = "Mumbai"; 
                      Console.WriteLine("{0},{1},{2},{3},{4}",mc[0],mc[1],mc[2],mc[3],mc[4]); 
                   } 
                } 
                

                Code project

                【讨论】:

                  【解决方案9】:

                  我记得有一次我在班级里有一个 long ,并且那个特定 long 的一些数字意味着什么(例如,如果第三个数字是 3,这意味着图表具有特定类型的编码,太可怕了系统我知道,但不是我发明的)

                  所以我做了这样的事情来返回数字的第 x 位:

                  protected int this[int index]
                  {
                      get
                      {
                          int tempN = Number;
                          if (index > 0)
                          {
                              tempN /= index * 10;
                          }
                          return tempN % 10;
                      }
                  }
                  

                  它受到保护是因为使用了不同的方法,所以它是一种帮手。当然,一个简单的 GetDigit(int a) 会是同样的事情(而且更不言自明),但当时我认为这是我认为使用索引器有意义的少数几次之一。自从 =(.

                  【讨论】:

                    【解决方案10】:

                    恕我直言,如果您想完善打包的 API,索引器可能是最好的选择 - 不值得为运行工厂业务对象付出努力。

                    如果您正在制作一些专门的集合,我会将其归类为修饰您的打包 API - 即使您将它们全部保存在一个模块中。

                    【讨论】:

                      猜你喜欢
                      • 2010-12-21
                      • 2010-09-08
                      • 2010-10-18
                      • 2011-02-22
                      • 1970-01-01
                      • 1970-01-01
                      • 2011-03-23
                      相关资源
                      最近更新 更多