Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
474 views
in Technique[技术] by (71.8m points)

.net - Implementation of different indexers within C# class

I'd like to add different indexer implementations in my class :

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

    }

So I need to know :

  1. How can I use the different indexer implementation?
  2. What are the best practises to implement differents kinds of indexation in this class?
  3. In which cases customizing indexation were better than using the different C# collections?
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Using explicit implementation of interfaces, you can do something like:

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

so implement two different enumerators with the same signature (where signature = type/number of input parameters). Note that you can have multiple interfaces, each one with an indexer with a different return type, so given x interfaces and one class, you can have x + 1 distinct indexers with the same signature.

Now... If Student was a "real" class instead of an object, you could do some tricks with implicit casts (you can't do implicit casts with/against the 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);
        //}
    }
}

(the indexer returns a MyObject class that then can be implicitly casted to int/string)

then use as

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

Note that I don't think this is a good idea. But you asked for it.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...