简体   繁体   English

C#-使用数组创建自定义列表时的最佳做法是什么

[英]C# - What are the best practices when creating custom lists using arrays

I've got some school work to practice some concepts like generics, delegates, and interfaces. 我有一些功课可以练习一些概念,例如泛型,委托和接口。 The whole project is to build a custom list class using an array of T . 整个项目是使用T数组构建自定义列表类。 the class should also implement IEnumerable and have a struct which is an IEnumerator . 类也应该实现IEnumerable ,有一个结构是一个IEnumerator I'm only focusing on the Add method here. 我在这里只关注Add方法。

class MyList<T> : IEnumerable
{
    private static readonly T[] arrayStarter = new T[1];
    private int capacity = 1;
    private int currentItems = 1;

    public T[] TList { get; set; }

    public MyList()
    {
        TList = arrayStarter;
        TList[0] = default(T);
    }

    public  T[] Add(T[] tArray, T item)
    {
        T[] temp = new T[++capacity];
        for (int i = 0; i < tArray.Length; i++)
            temp[i] = tArray[i];
        temp[tArray.Length] = item;
        currentItems++;
        return temp;
    }
}

When I'm creating an instance of my list and I want to add an item using the method it looks like this: 当我创建列表的实例时,我想使用以下方法添加项目:

MyList<int> m = new MyList<int>();
m.TList = m.Add(m.TList, 5);
m.TList = m.Add(m.TList, 7);
m.TList = m.Add(m.TList, 13);
m.TList = m.Add(m.TList, 15);

I'm pretty sure there's a better way to make a custom list I hope someone out there has a good insight on the matter. 我敢肯定,有一种更好的方法来制作自定义列表,希望在那里的人对此事有深入的了解。

This implementation demonstrates that you are missing the point of encapsulation in general, and of using private members in particular. 此实现表明,您总体上缺少封装的要点,尤其是缺少使用私有成员的要点。 Since you made TList array a member of your list class, you have an ability to hide it from your users completely. 由于您使TList数组成为列表类的成员,因此您可以将其完全向用户隐藏。 Your users should be able to write 您的用户应该能够写

m.Add(5);
m.Add(7);

instead of 代替

m.TList = m.Add(m.TList, 5);
m.TList = m.Add(m.TList, 7);

and not worry about m.TList 's presence at all. 完全不用担心m.TList的存在。

Fortunately, you can do it very easily: make TList a private field, rename it to something that starts in lower case letter to follow C#'s naming guidelines , remove it from the list of Add 's parameters, and change Add to not return anything. 幸运的是,您可以很容易地做到这一点:将TList私有字段,将其重命名为以小写字母开头的名称 ,以遵循C#的命名准则 ,将其从Add的参数列表中删除,然后将Add更改为不返回任何内容。 This would match IList<T> 's signature, which you should consider implementing. 这将匹配IList<T>的签名,您应该考虑实现该签名。

Once you've made this work, consider "divorcing" capacity from currentItems , letting the first one grow faster, and the other one catching up to it as more items are added. 完成这项工作后,请考虑从currentItems “分离” capacity ,让第一个更快地增长,而另一个随着更多项目的增加而赶上它。 This would reduce the number of re-allocations. 这将减少重新分配的次数。

As a final point, consider switching to using Array.Resize<T> to avoid manual copying of data. 最后,请考虑切换到使用Array.Resize<T>以避免手动复制数据。

If you take a look at List<> 's Add() method implementation in ReferenceSource or with ILSpy, you'll see this: 如果查看ReferenceSource或ILSpy中List<>Add()方法实现,您将看到以下内容:

private int _size;
private T[] _items;

public void Add(T item)
{
    if (this._size == this._items.Length)
    {
        this.EnsureCapacity(this._size + 1);
    }
    this._items[this._size++] = item;
    this._version++;
}

private void EnsureCapacity(int min)
{
    if (this._items.Length < min)
    {
        int num = (this._items.Length != 0) ? (this._items.Length * 2) : 4;
        if (num > 2146435071)
        {
            num = 2146435071;
        }
        if (num < min)
        {
            num = min;
        }
        this.Capacity = num;
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM