在类c#中对多个数组使用索引器

时间:2019-03-19 05:26:11

标签: c#

我的基类中有两个数组,我想创建可以在两个数组中使用的索引器,下面是我想做的MVCE。

class Indexer
      {
      private string[] namelist = new string[size];
      private char[] grades = new string[size];
      static public int size = 10;

      public IndexedNames() {
         for (int i = 0; i < size; i++){
            namelist[i] = "N. A.";
            grades[i] = 'F';
         }
      }
      public string this[int index] {
         get {
            string tmp;

            if( index >= 0 && index <= size-1 ) {
               tmp = namelist[index];
            } else {
               tmp = "";
            }

            return ( tmp );
         }
         set {
            if( index >= 0 && index <= size-1 ) {
               namelist[index] = value;
            }
         }
      }

在上述代码中,如果您注释掉了private char[] grades = new string[size];grades[i] = 'F';行,则可以将索引器用作object_name[i],但我希望能够同时访问namelistgrades由索引器组成。

注意:我无法像在应用程序中那样使用结构将它们包装在一起,因此大小可能并不总是相同。

这是否可行,或者我需要解决一些问题。

修改 我正在寻找类似names.namelist[i]names.grades[i]的东西,或者一些我可以分别访问它们的语句。同样,索引器逻辑也不是一致的,甚至在某些数组中大小也有所不同,此处跳过了这些索引,以简化MVCE。

3 个答案:

答案 0 :(得分:3)

对不起,不能做

尽管 Indexers 可以 Overloaded ,并且可以具有多个形式参数,但是您不能在相同的 Parameter 的基础上进行2个变化。同班。这是语言限制(或祝福)

Indexers (C# Programming Guide)

但是,这应该使您有几种选择。

  1. 您可以只使用C#7。 Ref returns
  

从C#7.0开始,C#支持参考返回值(参考   返回)。参考返回值允许方法返回   将变量而不是值的引用返回给调用者。的   然后,调用者可以选择将返回变量视为   按值或引用返回。呼叫者可以创建一个新的   变量本身就是对返回值的引用,称为a   ref local。

public ref string Namelist(int position)
{

     if (array == null)
         throw new ArgumentNullException(nameof(array));

     if (position < 0 || position >= array.Length)
         throw new ArgumentOutOfRangeException(nameof(position));

     return ref array[position];
}

...

// Which allows you to do funky things like this, ect.

object.NameList(1) = "bob";

  1. 您可以使用索引器创建子/嵌套类

这就是说,您可以创建一个具有索引器所需功能的类,并使它们成为主类的属性。因此,您得到的内容与您设想的object.Namelist[0]object.Grades[0]

注意 :在这种情况下,您可以将数组作为引用向下传递,并且仍然可以像您一样在主数组中访问它们


同时包含这两个示例

给出

public class GenericIndexer<T>
{
   private T[] _array;

   public GenericIndexer(T[] array)
   {
      _array = array;
   }
   public T this[int i]
   {
      get => _array[i];
      set => _array[i] = value;
   }
}

课程

public class Bobo
{
   private int[] _ints = { 2, 3, 4, 5, 5 };
   private string[] _strings = { "asd","asdd","sdf" };

   public Bobo()
   {

      Strings = new GenericIndexer<string>(_strings);
      Ints = new GenericIndexer<int>(_ints);
   }
   public GenericIndexer<string> Strings ;
   public GenericIndexer<int> Ints ;

   public void Test()
   {
      _ints[0] = 234;
   }

   public ref int DoInts(int pos)  => ref _ints[pos];
   public ref string DoStrings(int pos)  => ref _strings[pos];
}

用法

var bobo = new Bobo();
bobo.Ints[1] = 234;
bobo.DoInts(1) = 42;

答案 1 :(得分:1)

也许是这样的:

class Indexer
{
    private string[] namelist = new string[size];
    private string[] grades = new string[size + 1]; // size +1 to indicate different 
    // size
    static public int size = 10;

    public void IndexedNames()
    {
        for (int i = 0; i < size; i++)
        {
            namelist[i] = "N. A.";
            grades[i] = "F";
        }
    }

    public string this[int i, int j]
    {
        get
        {
            string tmp;

            // we need to return first array
            if (i > 0)
            {
                tmp = namelist[i];
            }
            else
            {
                tmp = grades[i];
            }

            return (tmp);
        }
        set
        {
            if (i > 0)
            {
                namelist[i] = value;
            }
            else grades[i] = value;
        }
    }
}

答案 2 :(得分:1)

我认为只有两个参数的索引器才能实现您想要的。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;

namespace ConsoleApp1
{
    class MyClass
    {
        protected static Dictionary<string, FieldInfo[]> table = new Dictionary<string, FieldInfo[]>();
        static public int size = 10;

        protected char[] grades = new char[size];

        public object this[string name, int index]
        {
            get
            {
                var fieldInfos = table[this.GetType().FullName];
                return ((Array)fieldInfos.First((x) => x.Name == name).GetValue(this)).GetValue(index);
            }
            set
            {
                var fieldInfos = table[this.GetType().FullName];
                ((Array)fieldInfos.First((x) => x.Name == name).GetValue(this)).SetValue(value, index);
            }
        }

        static void Main()
        {
            var names = new MyChildClass();
            names[DataColumns.Grades, 1] = 'S';
            names[DataColumns.NameList, 9] = "W.S";
        }
    }

    class MyChildClass : MyClass
    {
        private string[] namelist = new string[size];

        static MyChildClass()
        {
            var t = typeof(MyChildClass);
            table.Add(t.FullName, t.GetFields(BindingFlags.NonPublic | BindingFlags.Instance));
        }

        public MyChildClass()
        {
            for (int i = 0; i < size; i++)
            {
                namelist[i] = "N. A.";
                grades[i] = 'F';
            }
        }
    }

    static class DataColumns
    {
        public static string NameList = "namelist";
        public static string Grades = "grades";
    }
}