【问题标题】:C# Inherited Indexer: Another WayC# 继承索引器:另一种方式
【发布时间】:2012-06-15 09:57:14
【问题描述】:

我有一个抽象父类,它封装了对 MyObjects 数组的访问:

public abstract class MyObjectIterator
{
    public MyObjectIterator(MyObject[] MyObjects) { //constructor }

    public Vector2 [] Coords { //A Get Function }

    public Model[] Params { //A Get Function }

    //THIS ISN'T SAFE! CAN STILL CHANGE MEMBERS OF THE SET
    public MyObject[] MyObjects{ get; protected set; }
}

它的一个子类已经为另一个目的实现了一个索引索引器,所以我不能用它来返回一个 MyObject。
但是,由于返回数组是不安全/不好的做法,因为这意味着可以修改其中的元素,所以我正在寻找一种方法来提供一个整洁的接口来访问单个元素,例如

MyObject = Child.MyObjects[i];

但不提供 set 访问 MyObjects 的任何元素。

我的一个相关问题是:如果我在父类上有一个索引器,当你有一个子类的对象时可以使用它吗?

编辑:
我决定采用这种方法
public MyObject MyObject(int index) { return MyObjects[index]; } 因为它最能实现我想要的。

【问题讨论】:

  • 请注意,即使集合是只读的,返回的MyObjects 仍然可以编辑。如果这是一个问题,您可能想做一些事情来只公开对象的克隆,或者将 MyObjectclass 更改为 struct
  • IMO 如果您决定走那条路,最好使用索引器而不是方法。它在功能上非常相似,但允许更直接的声明和获取。您可能还希望实现IEnumerable<MyObject> 以允许以这种方式进行迭代。由于IEnumerable 仅指定读取权限,因此您不必公开任何设置功能。
  • @TimS,我想使用索引器,但由于子类使用相同的参数实现索引器,因此无法立即访问父类。因此问题是(子类有不同的返回类型;如果 C# 可以根据返回类型重载,那就太好了......)
  • 从技术上讲,.NET 框架允许基于返回类型的重载;但是,C# 没有。如果你真的想去写MSIL,你可以得到你想要的功能。否则,必须使用您的方法或 ReadOnly 路由(或除具有相同参数的索引器之外的任何东西)。

标签: c# inheritance indexer


【解决方案1】:

有一个ReadOnlyCollection 类可以完成您正在寻找的东西。这充当了数组的包装器。使用类似ReadOnlyCollection<MyObject> Data { get { return array.AsReadOnly(); } } 的东西改变底层数组会影响ReadOnlyCollection。该集合本身是相对轻量级的,因此您可以在每次访问该属性时创建一个新集合,或者如果频繁访问该属性(在调用站点或在类本身内),则使用缓存。

关于你的第二个问题,答案是肯定的。 Indexers in C# 很像属性。如果一个属性可以被继承(或需要,例如由于一个接口),那么索引器也是如此。

【讨论】:

  • 澄清一下,如果子类实现了自己的索引器,那么如果不强制转换为父类,则父类将不可用?
  • 是的;子实现将隐藏父的。但是如果您使用多态性,Parent[i] 将使用父级的实现而不是执行 Child[i] 的代码(如果索引器被隐藏而不是被覆盖[父级必须是虚拟的])。
猜你喜欢
  • 2013-09-03
  • 2012-03-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-08-11
  • 1970-01-01
  • 2020-08-27
  • 1970-01-01
相关资源
最近更新 更多