自定义集合抛出错误的扩展方法

时间:2013-12-13 03:01:36

标签: c# linq extension-methods ienumerator

我正在创建这样的自定义集合。

 public class ClientBusinessEntityCollection<T> : ICollection<T> where T : EntityBase
{
    /// <summary>
    /// The list business objects
    /// </summary>
    private List<T> listBusinessObjects = null;

    /// <summary>
    /// Initializes a new instance of the <see cref="KddiBusinessEntityCollection{T}"/> class.
    /// </summary>
    public ClientBusinessEntityCollection()
    {
        this.listBusinessObjects = new List<T>();
    }

    /// <summary>
    /// Initializes a new instance of the <see cref="KddiBusinessEntityCollection{T}"/> class.
    /// </summary>
    /// <param name="collection">The collection.</param>
    public ClientBusinessEntityCollection(IEnumerable<T> collection)
    {
        this.listBusinessObjects = new List<T>(collection);
    }

    /// <summary>
    /// Gets the number of elements contained in the <see cref="T:System.Collections.Generic.ICollection`1" />.
    /// </summary>
    /// <value>The count.</value>
    /// <returns>The number of elements contained in the <see cref="T:System.Collections.Generic.ICollection`1" />.</returns>
    public int Count
    {
        get { return this.listBusinessObjects.Count; }
    }

    /// <summary>
    /// Gets the <see cref="`0"/> at the specified index.
    /// </summary>
    /// <param name="index">The index.</param>
    /// <returns>`0.</returns>
    public T this[long index]
    {
        get
        {
            return this.listBusinessObjects[(int)index];
        }
    }

    /// <summary>
    /// Gets a value indicating whether the <see cref="T:System.Collections.Generic.ICollection`1" /> is read-only.
    /// </summary>
    /// <value><c>true</c> if this instance is read only; otherwise, <c>false</c>.</value>
    /// <returns>true if the <see cref="T:System.Collections.Generic.ICollection`1" /> is read-only; otherwise, false.</returns>
    public bool IsReadOnly
    {
        get { return false; }
    }

    /// <summary>
    /// Adds an item to the <see cref="T:System.Collections.Generic.ICollection`1" />.
    /// </summary>
    /// <param name="item">The object to add to the <see cref="T:System.Collections.Generic.ICollection`1" />.</param>
    public void Add(T item)
    {
        this.listBusinessObjects.Add(item);
    }

    /// <summary>
    /// Removes all items from the <see cref="T:System.Collections.Generic.ICollection`1" />.
    /// </summary>
    public void Clear()
    {
        this.listBusinessObjects.Clear();
    }

    /// <summary>
    /// Determines whether the <see cref="T:System.Collections.Generic.ICollection`1" /> contains a specific value.
    /// </summary>
    /// <param name="item">The object to locate in the <see cref="T:System.Collections.Generic.ICollection`1" />.</param>
    /// <returns>true if <paramref name="item" /> is found in the <see cref="T:System.Collections.Generic.ICollection`1" />; otherwise, false.</returns>
    public bool Contains(T item)
    {
        return this.listBusinessObjects.Contains(item);
    }

    /// <summary>
    /// Sorts the collection.
    /// </summary>
    /// <param name="sorter">The sorter.</param>
    public void SortCollection(Func<EntityBase, object> sorter)
    {
        //// TODO : IMPLEMENT SORTING HERE.
    }

    /// <summary>
    /// Copies to.
    /// </summary>
    /// <param name="array">The array.</param>
    /// <param name="arrayIndex">Index of the array.</param>
    public void CopyTo(T[] array, int arrayIndex)
    {
    }

    /// <summary>
    /// Removes the first occurrence of a specific object from the <see cref="T:System.Collections.Generic.ICollection`1" />.
    /// </summary>
    /// <param name="item">The object to remove from the <see cref="T:System.Collections.Generic.ICollection`1" />.</param>
    /// <returns>true if <paramref name="item" /> was successfully removed from the <see cref="T:System.Collections.Generic.ICollection`1" />; otherwise, false. This method also returns false if <paramref name="item" /> is not found in the original <see cref="T:System.Collections.Generic.ICollection`1" />.</returns>
    public bool Remove(T item)
    {
        return this.listBusinessObjects.Remove(item);
    }

    /// <summary>
    /// Returns an enumerator that iterates through the collection.
    /// </summary>
    /// <returns>A <see cref="T:System.Collections.Generic.IEnumerator`1" /> that can be used to iterate through the collection.</returns>
    public IEnumerator<T> GetEnumerator()
    {
        return this.listBusinessObjects.GetEnumerator();
    }

    /// <summary>
    /// Returns an enumerator that iterates through a collection.
    /// </summary>
    /// <returns>An <see cref="T:System.Collections.IEnumerator" /> object that can be used to iterate through the collection.</returns>
    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
    {
        return this.listBusinessObjects.GetEnumerator();
    }
}

现在我有一个像这样的集合

public ClientBusinessEntityCollection<MyClass> Collection {get; set;}

现在的问题是,当我在“Collection”上编写LINQ语句时,它会抛出空引用异常。

Collection.OrderBy(item=>item.Order);

该集合有一个基础列表,但与将鼠标悬停在我的自定义“集合”上时不同,它没有显示项目数。在我的自定义集合上编写LINQ时,如何从基础List对象中选择扩展方法?

我是否需要编写自定义IEnumerator?

1 个答案:

答案 0 :(得分:0)

您需要将与集合相关的任何与调查器相关的调用传递给基础列表,如下所示:

public class MyTest<T> : ICollection<T>
{
    private List<T> myUnderlyingList = new List<T>();

    public IEnumerator<T> GetEnumerator()
    {
        return myUnderlyingList.GetEnumerator();
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }

.... etc.

然后LINQ只会在执行其操作时“看到”基础列表。

另一件事是要确保在运行任何LINQ方法之前,使用有效数据正确填充底层List<T>