在 C# 中实现不同的索引器 class

Implementation of different indexers within C# class

我想在我的 class 中添加不同的索引器实现:

特定集合

 public class SpecificCollection<T> : ISpecificCollection <T>
    {
        public int this[int index]
        {
            get
            {
                throw new NotImplementedException();
            }
            set
            {
                throw new NotImplementedException();
            }
        }

       public object  this[int index]
        {
            get
            {
                throw new NotImplementedException();
            }
            set
            {
                throw new NotImplementedException();
            }
        }

       public string  this[int index]
        {
            get
            {
                throw new NotImplementedException();
            }
            set
            {
                throw new NotImplementedException();
            }
        }

        public event void OnAddElement;

        public event void OnRemoveElement;

        public void AddNewElement(T element)
        {
            throw new NotImplementedException();
        }

        public void DeleteElement(int index)
        {
            throw new NotImplementedException();
        }

        public int Count
        {
            get
            {
                throw new NotImplementedException();
            }
            set
            {
                throw new NotImplementedException();
            }
        }
    }

StudentSpecificCollection

 public class StudentSpecificCollection : SpecificCollection<Student>
    {

       private string[] arrName;
       private int[] arrAge;
       private object[] arrStudent ;

       public int ISpecificCollectionIndexers<Student>.this[int index]
        {
            get
            {
                return arrAge[index];
            }
            set
            {
                arrAge[index] = value;
            }
        }

        object ISpecificCollectionIndexers<Student>.this[int index]
        {
            get
            {
                return arrStudent[index];
            }
            set
            {
                arrStudent[index] = value;
            }
        }

        string ISpecificCollectionIndexers<Student>.this[int index]
        {
            get
            {
                return arrName[index];
            }
            set
            {
                arrName[index] = value;
            }
        }

        public event void OnAddElement;

        public event void OnRemoveElement;

        public void AddNewElement(Student element)
        {
            object objStudent = arrStudent.Where(x => x != null).LastOrDefault();
            int index = (objStudent == null) ? 0 : Array.IndexOf(arrStudent, objStudent);
            arrName[index] = element.Name ;
            arrAge[index] = element.Age;
            arrStudent[index] = element;
        }

        public void DeleteElement(int index)
        {
            if (index > Count - 1) return;
            arrName[index] = null;
            arrAge[index] = -1;
            arrStudent[index] = null;
        }

        public int Count
        {
            get
            {
                return arrName.Where(x=>x !=null).Count();
            }
            set
            { 
            }
        }
        public StudentSpecificCollection()
        {
            arrName = new string[100];
            arrAge = new int[100];
            arrStudent = new object[100];
        }

    }

所以我需要知道:

  1. 如何使用不同的索引器实现?
  2. 在此 class 中实施不同类型索引的最佳做法是什么?
  3. 在哪些情况下自定义索引比使用不同的 C# 集合更好?

一样,return 类型不是方法签名的一部分。所以你不能像你的代码中那样做。

您可以使用显式接口提供多个索引器,如 中所示。

虽然代码没有任何意义。只需使用一个索引器并存储 return 学生对象,这样您就可以 string name = lstStudent[0].Name;.

使用接口的显式实现,你可以做如下事情:

public interface IMyClass
{
    object this[int index]
    {
        get; set;
    }
}

public class MyClass : IMyClass
{
    public string this[int index]
    {
        get
        {
            return "";
        }

        set
        {
        }
    }

    object IMyClass.this[int index]
    {
        get
        {
            return "";
        }

        set
        {
        }
    }
}

因此实现两个具有相同签名的不同枚举器(其中签名 = type/number 输入参数)。请注意,您可以有多个接口,每个接口都有一个具有不同 return 类型的索引器,因此给定 x 个接口和一个 class,您可以有 x + 1 个具有相同签名的不同索引器。

现在...如果 Student 是 "real" class 而不是 object,你可以用隐式转换做一些技巧(你不能做隐式转换 with/against object class):

public class StudentSpecificCollection
{
    private string[] arrName;
    private int[] arrAge;
    private object[] arrStudent;

    public MyObject this[int index]
    {
        get
        {
            return new MyObject(this, index);
        }

        set
        {
            if (value.Type.HasFlag(MyObject.MyObjectType.Name))
            {
                arrName[index] = value;
            }

            if (value.Type.HasFlag(MyObject.MyObjectType.Age))
            {
                arrAge[index] = value;
            }

            if (value.Type.HasFlag(MyObject.MyObjectType.Student))
            {
                arrStudent[index] = value;
            }
        }
    }

    public class MyObject
    {
        [Flags]
        public enum MyObjectType
        {
            Name = 1,
            Age = 2,
            Student = 4
        }

        public readonly MyObjectType Type;
        public readonly string Name;
        public readonly int Age;
        public readonly object Student;

        protected MyObject(string name)
        {
            Type = MyObjectType.Name;
            Name = name;
        }

        protected MyObject(int age)
        {
            Type = MyObjectType.Age;
            Age = age;
        }

        protected MyObject(object student)
        {
            Type = MyObjectType.Student;
            Student = student;
        }

        public MyObject(StudentSpecificCollection obj, int ix)
        {
            Name = obj.arrName[ix];
            Age = obj.arrAge[ix];
            Student = obj.arrStudent[ix];
        }

        public static implicit operator string(MyObject obj)
        {
            if (!obj.Type.HasFlag(MyObjectType.Name))
            {
                throw new Exception();
            }

            return obj.Name;
        }

        public static implicit operator int(MyObject obj)
        {
            if (!obj.Type.HasFlag(MyObjectType.Age))
            {
                throw new Exception();
            }

            return obj.Age;
        }

        //public static implicit operator object(MyObject obj)
        //{
        //    if (!obj.Type.HasFlag(MyObjectType.Student))
        //    {
        //        throw new Exception();
        //    }

        //    return obj.Student;
        //}

        public static implicit operator MyObject(string name)
        {
            return new MyObject(name);
        }

        public static implicit operator MyObject(int age)
        {
            return new MyObject(age);
        }

        //public static implicit operator MyObject(object student)
        //{
        //    return new MyObject(student);
        //}
    }
}

(索引器 return 是一个 MyObject class 然后可以隐式转换为 int/string

然后用作

var obj = new StudentSpecificCollection();
// Load some students here
obj[0] = "Foo";
obj[0] = 25;
string name = obj[0];
int age = obj[0];

请注意,我认为这是个好主意。但是要求的。