| File: System\ServiceModel\SynchronizedCollection.cs | Web Access |
| Project: src\src\System.ServiceModel.Primitives\src\System.ServiceModel.Primitives.csproj (System.ServiceModel.Primitives) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. using System.ServiceModel; using System.Reflection; namespace System.Collections.Generic { [Runtime.InteropServices.ComVisible(false)] public class SynchronizedCollection<T> : IList<T>, IList { private object _sync; public SynchronizedCollection() { Items = new List<T>(); _sync = new Object(); } public SynchronizedCollection(object syncRoot) { Items = new List<T>(); _sync = syncRoot ?? throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException(nameof(syncRoot))); } public SynchronizedCollection(object syncRoot, IEnumerable<T> list) { if (list == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException(nameof(list))); } Items = new List<T>(list); _sync = syncRoot ?? throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException(nameof(syncRoot))); } public SynchronizedCollection(object syncRoot, params T[] list) { if (list == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException(nameof(list))); } Items = new List<T>(list.Length); for (int i = 0; i < list.Length; i++) { Items.Add(list[i]); } _sync = syncRoot ?? throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException(nameof(syncRoot))); } public int Count { get { lock (_sync) { return Items.Count; } } } protected List<T> Items { get; } public object SyncRoot { get { return _sync; } } public T this[int index] { get { lock (_sync) { return Items[index]; } } set { lock (_sync) { if (index < 0 || index >= Items.Count) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException(nameof(index), index, SRP.Format(SRP.ValueMustBeInRange, 0, Items.Count - 1))); } SetItem(index, value); } } } public void Add(T item) { lock (_sync) { int index = Items.Count; InsertItem(index, item); } } public void Clear() { lock (_sync) { ClearItems(); } } public void CopyTo(T[] array, int index) { lock (_sync) { Items.CopyTo(array, index); } } public bool Contains(T item) { lock (_sync) { return Items.Contains(item); } } public IEnumerator<T> GetEnumerator() { lock (_sync) { return Items.GetEnumerator(); } } public int IndexOf(T item) { lock (_sync) { return InternalIndexOf(item); } } public void Insert(int index, T item) { lock (_sync) { if (index < 0 || index > Items.Count) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException(nameof(index), index, SRP.Format(SRP.ValueMustBeInRange, 0, Items.Count))); } InsertItem(index, item); } } private int InternalIndexOf(T item) { int count = Items.Count; for (int i = 0; i < count; i++) { if (object.Equals(Items[i], item)) { return i; } } return -1; } public bool Remove(T item) { lock (_sync) { int index = InternalIndexOf(item); if (index < 0) { return false; } RemoveItem(index); return true; } } public void RemoveAt(int index) { lock (_sync) { if (index < 0 || index >= Items.Count) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException(nameof(index), index, SRP.Format(SRP.ValueMustBeInRange, 0, Items.Count - 1))); } RemoveItem(index); } } protected virtual void ClearItems() { Items.Clear(); } protected virtual void InsertItem(int index, T item) { Items.Insert(index, item); } protected virtual void RemoveItem(int index) { Items.RemoveAt(index); } protected virtual void SetItem(int index, T item) { Items[index] = item; } bool ICollection<T>.IsReadOnly { get { return false; } } IEnumerator IEnumerable.GetEnumerator() { return ((IList)Items).GetEnumerator(); } bool ICollection.IsSynchronized { get { return true; } } object ICollection.SyncRoot { get { return _sync; } } void ICollection.CopyTo(Array array, int index) { lock (_sync) { ((IList)Items).CopyTo(array, index); } } object IList.this[int index] { get { return this[index]; } set { VerifyValueType(value); this[index] = (T)value; } } bool IList.IsReadOnly { get { return false; } } bool IList.IsFixedSize { get { return false; } } int IList.Add(object value) { VerifyValueType(value); lock (_sync) { Add((T)value); return Count - 1; } } bool IList.Contains(object value) { VerifyValueType(value); return Contains((T)value); } int IList.IndexOf(object value) { VerifyValueType(value); return IndexOf((T)value); } void IList.Insert(int index, object value) { VerifyValueType(value); Insert(index, (T)value); } void IList.Remove(object value) { VerifyValueType(value); Remove((T)value); } private static void VerifyValueType(object value) { if (value == null) { if (typeof(T).GetTypeInfo().IsValueType) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SRP.SynchronizedCollectionWrongTypeNull)); } } else if (!(value is T)) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SRP.Format(SRP.SynchronizedCollectionWrongType1, value.GetType().FullName))); } } } }