提问者:小点点

操作从列表或集合派生的类


我试图通过将列表“合并”到一个新的类中来使其更加用户友好,但是从新的类中访问列表的特定功能和属性会给我带来麻烦。

下面是一个例子:

public class Words : List<Word>
{
    public uint BytesPerWord { get; protected set; }

    public Word this[int index] => this.ElementAt(index);
  
    /*  public new Words GetRange(int index, int count)
    {
        var a = this.GetRange(index, count);

        return a;
    }*/

    public Words(uint bytesPerWord) : base()
    {
        BytesPerWord = bytesPerWord;
    }
}

现在,我试着从别处提取一些“words”类型的单词,通过这样做,把它们的一部分提取到我的单词中:

Words myWords = someOtherWords.GetRange((int)X, (int)Y);

这里有几个问题:

  • GetRange不可访问。 因此,我试图创建它的新版本(上面注释掉了),但是“this.getRange()”创建了一个stackOverflow异常。
  • 还“word this[int index]”抱怨隐藏的继承成员--但我猜这与前面的问题有关

我们非常感谢您提出如何修复此问题的任何建议。
请注意,我还尝试用集合替换List,因为我已经读过“我不应该从List派生”,但这并没有什么区别。


共2个答案

匿名用户

根据经验,您不应该从list派生; 它有很多你可能不想继承的行为。

为了避免重蹈覆辙,您可以通过组合使用list<;t>:

public class Words
{
    private readonly List<Word> _list; // Composition

    public uint BytesPerWord { get; protected set; }
    public Word this[int index] => _list[index];
  
    public Words GetRange(int index, int count)
    {
        var a = _list.GetRange(index, count);
        return new Words(BytesPerWord, a);
    }

    public Words(uint bytesPerWord) : this(bytesPerWord, new List<Word>()) { }

    private Words(uint bytesPerWord, List<Word> list)
    {
        BytesPerWord = bytesPerWord;
        _list = list;
    }
}

如果需要类是可枚举的,甚至可以实现IEnumerable:

public class Words : IEnumerable<Word>
{
    private readonly List<Word> _list;

    //...

    public IEnumerator<Word> GetEnumerator() => _list.GetEnumerator();

    IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}

这同样适用于其他集合接口。

匿名用户

您的代码无法工作,因为您在方法GetRange中调用this.GetRange(而不是base.GetRange),这将创建一个无限循环,直到发生stackoverflow异常。

因此您可以将代码更改为

public class Words : List<Word>
{
    public uint BytesPerWord { get; protected set; }
    public new Word this[int index] => this.ElementAt(index);

    public new Words GetRange(int index, int count)
    {
        var a = base.GetRange(index, count);
        Words copy = new Words(100);
        copy.AddRange(a);
        return copy;
    }

然而,我有点困惑,这将如何帮助您的代码的可读性。 如果您不需要向列表添加任何新功能,那么我认为隐藏变量的真实性质不是一个好主意。

还要注意这一行:

public Word this[int index] => this.ElementAt(index);

可以在新修饰符之前编写,并可选地引用基类

public new Word this[int index] => base[index];

反对这个类有用的另一个原因。