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

时间:2015-03-11 11:00:16

标签: c# .net oop collections interface

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

SpecificCollection

 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. 在此课程中实施不同种类的索引的最佳做法是什么?
  3. 在哪些情况下,自定义索引比使用不同的C#集合更好?

2 个答案:

答案 0 :(得分:4)

使用接口的显式实现,您可以执行以下操作:

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

所以实现具有相同签名的两个不同的枚举器(其中signature =输入参数的类型/数量)。请注意,您可以拥有多个接口,每个接口都有一个具有不同返回类型的索引器,因此,如果给定x接口和一个类,则可以使x + 1个不同的索引器具有相同的签名。

现在......如果Student是一个“真正的”类而不是object,你可以使用隐式强制转换做一些技巧(你不能对{{进行隐式强制转换) 1}} class):

object

(索引器返回一个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); //} } } 类,然后可以隐式转换为MyObject / int

然后用作

string

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

答案 1 :(得分:3)

作为noted by Spoi1ler,返回类型不是方法签名的一部分。所以你不能像你的代码中所示那样做。

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

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