JD2022-TU1/main/tools/framework/JD.Collections/ObjectModel/CollectionBase.cs

334 lines
11 KiB
C#

using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using JD.Collections.Details;
using JD.Collections.Utilities;
using JD.Kernel.StaticHelpers;
namespace JD.Collections.ObjectModel
{
/// <summary>
/// CollectionBase is a base class that can be used to more easily implement the
/// generic ICollection&lt;T&gt; and non-generic ICollection interfaces.
/// </summary>
/// <remarks>
/// <para>To use CollectionBase as a base class, the derived class must override
/// the <see cref="Count"/>, <see cref="GetEnumerator"/>, <see cref="Add"/>, <see cref="Clear"/>, and <see cref="Remove"/> methods. </para>
/// <para><see cref="ICollection{T}.Contains"/> need not be implemented by the
/// derived class, but it should be strongly considered, because the CollectionBase implementation
/// may not be very efficient.</para>
/// </remarks>
/// <typeparam name="T">The item type of the collection.</typeparam>
[Serializable]
[DebuggerDisplay("Count = {Count}"), DebuggerTypeProxy(typeof(CollectionBase<>.DebugView))]
public abstract class CollectionBase<T> : ICollection<T>, ICollection
{
#region Inner Types
private sealed class DebugView
{
#region Variables
private readonly ICollection<T> m_collection;
#endregion
#region Constructor
/// <summary>
/// Constructor.
/// </summary>
/// <param name="collection"></param>
public DebugView(CollectionBase<T> collection)
{
Throw.IfNull(collection, "collection");
m_collection = collection;
}
#endregion
#region Properties
/// <summary>
/// Items.
/// </summary>
[DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]
public T[] Items
{
get
{
T[] array = new T[m_collection.Count];
m_collection.CopyTo(array, 0);
return array;
}
}
#endregion
}
#endregion
#region Constructor
/// <summary>
/// Creates a new CollectionBase.
/// </summary>
protected CollectionBase()
{
}
#endregion
#region Misc members
/// <summary>
/// Shows the string representation of the collection. The string representation contains
/// a list of the items in the collection. Contained collections (except strings) are expanded
/// recursively.
/// </summary>
/// <returns>The string representation of the collection.</returns>
public override string ToString()
{
return new CollectionPrinter().Print(this);
}
/// <summary>
/// Displays the contents of the collection in the debugger. This is intentionally private, it is called
/// only from the debugger due to the presence of the DebuggerDisplay attribute. It is similar
/// format to ToString(), but is limited to 250-300 characters or so, so as not to overload the debugger.
/// </summary>
/// <returns>The string representation of the items in the collection, similar in format to ToString().</returns>
internal string DebuggerDisplayString()
{
const int MAXLENGTH = 250;
System.Text.StringBuilder builder = new System.Text.StringBuilder();
builder.Append('{');
// Call ToString on each item and put it in.
bool firstItem = true;
foreach (T item in this)
{
if (builder.Length >= MAXLENGTH)
{
builder.Append(",...");
break;
}
if (!firstItem)
builder.Append(',');
if (item == null)
builder.Append("null");
else
builder.Append(item.ToString());
firstItem = false;
}
builder.Append('}');
return builder.ToString();
}
#endregion
#region ICollection<T> Members
/// <summary>
/// Must be overridden to allow adding items to this collection.
/// </summary>
/// <param name="item">Item to be added to the collection.</param>
public abstract void Add(T item);
/// <summary>
/// Must be overridden to allow clearing this collection.
/// </summary>
public abstract void Clear();
/// <summary>
/// Must be overridden to allow removing items from this collection.
/// </summary>
/// <returns>True if <paramref name="item"/> existed in the collection and
/// was removed. False if <paramref name="item"/> did not exist in the collection.</returns>
public abstract bool Remove(T item);
/// <summary>
/// Determines if the collection contains a particular item. This default implementation
/// iterates all of the items in the collection via GetEnumerator, testing each item
/// against <paramref name="item"/> using IComparable&lt;T&gt;.Equals or
/// Object.Equals.
/// </summary>
/// <remarks>You should strongly consider overriding this method to provide
/// a more efficient implementation, or if the default equality comparison
/// is inappropriate.</remarks>
/// <param name="item">The item to check for in the collection.</param>
/// <returns>True if the collection contains <paramref name="item"/>, false otherwise.</returns>
public virtual bool Contains(T item)
{
IEqualityComparer<T> equalityComparer = EqualityComparer<T>.Default;
foreach (T i in this)
{
if (equalityComparer.Equals(i, item))
{
return true;
}
}
return false;
}
/// <summary>
/// Copies all the items in the collection into an array. Implemented by
/// using the enumerator returned from GetEnumerator to get all the items
/// and copy them to the provided array.
/// </summary>
/// <param name="array">Array to copy to.</param>
/// <param name="arrayIndex">Starting index in <paramref name="array"/> to copy to.</param>
public virtual void CopyTo(T[] array, int arrayIndex)
{
int count = this.Count;
if (count == 0)
{
return;
}
Throw.IfNull(array, "array");
Throw.ArgumentOutOfRangeIf(count < 0, "count", Strings.ArgMustNotBeNegative);
Throw.ArgumentOutOfRangeIf(arrayIndex < 0, "arrayIndex", Strings.ArgMustNotBeNegative);
Throw.InvalidArgumentIf(arrayIndex >= array.Length || count > array.Length - arrayIndex, "array", Strings.ArrayTooSmall);
int index = arrayIndex, i = 0;
foreach (T item in this)
{
if (i >= count)
{
break;
}
array[index] = item;
++index;
++i;
}
}
/// <summary>
/// Creates an array of the correct size, and copies all the items in the
/// collection into the array, by calling CopyTo.
/// </summary>
/// <returns>An array containing all the elements in the collection, in order.</returns>
public virtual T[] ToArray()
{
int count = this.Count;
T[] array = new T[count];
CopyTo(array, 0);
return array;
}
/// <summary>
/// Must be overridden to provide the number of items in the collection.
/// </summary>
/// <value>The number of items in the collection.</value>
public abstract int Count { get; }
/// <summary>
/// Indicates whether the collection is read-only. Always returns false.
/// </summary>
/// <value>Always returns false.</value>
bool ICollection<T>.IsReadOnly
{
get { return IsReadOnly; }
}
protected virtual bool IsReadOnly
{
get { return false; }
}
#endregion
#region IEnumerable<T> Members
/// <summary>
/// Must be overridden to enumerate all the members of the collection.
/// </summary>
/// <returns>A generic <see cref="IEnumerator{T}"/> that can be used to enumerate all the items in the collection.</returns>
public abstract IEnumerator<T> GetEnumerator();
#endregion
#region ICollection Members
/// <summary>
/// Copies all the items in the collection into an array. Implemented by
/// using the enumerator returned from GetEnumerator to get all the items
/// and copy them to the provided array.
/// </summary>
/// <param name="array">Array to copy to.</param>
/// <param name="index">Starting index in <paramref name="array"/> to copy to.</param>
void ICollection.CopyTo(Array array, int index)
{
int count = this.Count;
if (count == 0)
{
return;
}
Throw.IfNull(array, "array");
Throw.ArgumentOutOfRangeIf(index < 0, "index", Strings.ArgMustNotBeNegative);
Throw.ArgumentOutOfRangeIf(index >= array.Length || count > array.Length - index, "index", Strings.ArrayTooSmall);
int i = 0;
foreach (object o in this)
{
if (i >= count)
{
break;
}
array.SetValue(o, index);
++index;
++i;
}
}
/// <summary>
/// Indicates whether the collection is synchronized.
/// </summary>
/// <value>Always returns false, indicating that the collection is not synchronized.</value>
bool ICollection.IsSynchronized
{
get { return false; }
}
/// <summary>
/// Indicates the synchronization object for this collection.
/// </summary>
/// <value>Always returns this.</value>
object ICollection.SyncRoot
{
get { return this; }
}
#endregion
#region IEnumerable Members
/// <summary>
/// Provides an IEnumerator that can be used to iterate all the members of the
/// collection. This implementation uses the IEnumerator&lt;T&gt; that was overridden
/// by the derived classes to enumerate the members of the collection.
/// </summary>
/// <returns>An IEnumerator that can be used to iterate the collection.</returns>
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
#endregion
}
}