【问题标题】:Implementation of different indexers within C# class在 C# 类中实现不同的索引器
【发布时间】:2015-05-13 03:17:36
【问题描述】:

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

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# 集合更好?

【问题讨论】:

  • 您不能创建仅在返回类型上有所不同的方法的重载。
  • @Spo1ler 谢谢,我不是在问错误的原因很清楚,但我需要一个建议来实现不同类型的索引器
  • 您只能让一个索引器返回您所在班级的对象,名称和年龄等属性可以通过该对象访问。
  • @LamloumiAfif 你可以实现接口
  • 您的代码没有意义。为什么不将Student 对象本身存储在一个集合中?

标签: c# .net oop collections interface


【解决方案1】:

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

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

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

【讨论】:

  • 我不是在问错误的原因很清楚,我需要一个建议来实现不同类型的索引器
【解决方案2】:

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

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

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

现在...如果Student 是一个“真实”类而不是object,您可以使用隐式转换做一些技巧(您不能使用/反对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

然后用作

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

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

【讨论】:

  • 这行得通。 但是您必须通过接口 (((IMyClass)instance)[0]) 访问该类,这很麻烦。看起来 OP 不应该为此使用索引器。
  • @xanatos:谢谢,@CodeCaster 你是对的,我需要让它像instance[0] 一样,而不需要转换到界面
  • 让编译器变傻的好方法:)
  • @LamloumiAfif 我不知道你是否注意到第二个例子......我认为这是个好主意,但它可能对其他事情有用.
猜你喜欢
  • 2013-01-28
  • 1970-01-01
  • 1970-01-01
  • 2021-12-05
  • 2010-11-26
  • 2016-05-05
  • 2011-02-17
  • 2010-10-15
  • 1970-01-01
相关资源
最近更新 更多