Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: implement generic IList interface #2749

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,18 @@
#nullable disable

using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;

namespace System.Windows.Forms
{
internal class ArraySubsetEnumerator : IEnumerator
internal class ArraySubsetEnumerator<T> : IEnumerator<T>
{
private readonly object[] _array;
private readonly T[] _array;
private readonly int _total;
private int _current;

public ArraySubsetEnumerator(object[] array, int count)
public ArraySubsetEnumerator(T[] array, int count)
{
Debug.Assert(count == 0 || array != null, "if array is null, count should be 0");
Debug.Assert(array == null || count <= array.Length, "Trying to enumerate more than the array contains");
Expand All @@ -24,6 +25,8 @@ public ArraySubsetEnumerator(object[] array, int count)
_current = -1;
}

void IDisposable.Dispose() { }

public bool MoveNext()
{
if (_current < _total - 1)
Expand All @@ -37,6 +40,8 @@ public bool MoveNext()

public void Reset() => _current = -1;

public object Current => _current == -1 ? null : _array[_current];
public T Current => _current == -1 ? default : _array[_current];

object IEnumerator.Current => Current;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,16 @@
#nullable disable

using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;

namespace System.Windows.Forms
{
/// <summary>
/// Represents a collection of strings.
/// </summary>
public class AutoCompleteStringCollection : IList
public class AutoCompleteStringCollection : IList, IList<string>
{
CollectionChangeEventHandler onCollectionChanged;
private readonly ArrayList data = new ArrayList();
Expand Down Expand Up @@ -88,6 +90,8 @@ public int Add(string value)
return index;
}

void ICollection<string>.Add(string value) => Add(value);

/// <summary>
/// Copies the elements of a string array to the end of the <see cref='AutoCompleteStringCollection'/>.
/// </summary>
Expand Down Expand Up @@ -175,10 +179,18 @@ public bool IsSynchronized
/// <summary>
/// Removes a specific string from the <see cref='AutoCompleteStringCollection'/> .
/// </summary>
public void Remove(string value)
public void Remove(string value) => TryRemove(value);

bool ICollection<string>.Remove(string value) => TryRemove(value);

private bool TryRemove(string value)
Comment on lines +182 to +186
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this PR iteration instead of changing return type of public Remove methods I instead add a private TryRemove method to avoid code duplication so that interfaces can use the same call.

{
if (!data.Contains(value))
return false;

data.Remove(value);
OnCollectionChanged(new CollectionChangeEventArgs(CollectionChangeAction.Remove, value));
return true;
}

/// <summary>
Expand Down Expand Up @@ -238,9 +250,11 @@ void ICollection.CopyTo(Array array, int index)
data.CopyTo(array, index);
}

public IEnumerator GetEnumerator()
public IEnumerator<string> GetEnumerator()
{
return data.GetEnumerator();
return data.Cast<string>().GetEnumerator();
}

IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,16 @@

using System.ComponentModel;
using System.Collections;
using System.Collections.Generic;
using System.Linq;

namespace System.Windows.Forms
{
/// <summary>
/// Represents a collection of data bindings on a control.
/// </summary>
[DefaultEvent(nameof(CollectionChanged))]
public class BindingsCollection : BaseCollection
public class BindingsCollection : BaseCollection, IReadOnlyList<Binding>
{
private ArrayList _list;
private CollectionChangeEventHandler _onCollectionChanging;
Expand Down Expand Up @@ -121,5 +123,13 @@ internal protected void Remove(Binding binding)
protected virtual void RemoveCore(Binding dataBinding) => List.Remove(dataBinding);

internal protected bool ShouldSerializeMyAll() => Count > 0;

public new IEnumerator<Binding> GetEnumerator()
{
if (_list is null)
return Enumerable.Empty<Binding>().GetEnumerator();
else
return _list.Cast<Binding>().GetEnumerator();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#nullable disable

using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
Expand Down Expand Up @@ -1093,7 +1094,7 @@ public int Add(object item, CheckState check)
}
}

public class CheckedIndexCollection : IList
public class CheckedIndexCollection : IList, IList<int>
{
private readonly CheckedListBox owner;

Expand Down Expand Up @@ -1171,26 +1172,57 @@ object IList.this[int index]
}
}

int IList<int>.this[int index]
{
get => this[index];
set => throw new NotSupportedException(SR.CheckedListBoxCheckedIndexCollectionIsReadOnly);
}

void ICollection<int>.Add(int value)
{
throw new NotSupportedException(SR.CheckedListBoxCheckedIndexCollectionIsReadOnly);
}

int IList.Add(object value)
{
throw new NotSupportedException(SR.CheckedListBoxCheckedIndexCollectionIsReadOnly);
}

void ICollection<int>.Clear()
{
throw new NotSupportedException(SR.CheckedListBoxCheckedIndexCollectionIsReadOnly);
}

void IList.Clear()
{
throw new NotSupportedException(SR.CheckedListBoxCheckedIndexCollectionIsReadOnly);
}

void IList<int>.Insert(int index, int value)
{
throw new NotSupportedException(SR.CheckedListBoxCheckedIndexCollectionIsReadOnly);
}

void IList.Insert(int index, object value)
{
throw new NotSupportedException(SR.CheckedListBoxCheckedIndexCollectionIsReadOnly);
}

bool ICollection<int>.Remove(int value)
{
throw new NotSupportedException(SR.CheckedListBoxCheckedIndexCollectionIsReadOnly);
}

void IList.Remove(object value)
{
throw new NotSupportedException(SR.CheckedListBoxCheckedIndexCollectionIsReadOnly);
}

void IList<int>.RemoveAt(int index)
{
throw new NotSupportedException(SR.CheckedListBoxCheckedIndexCollectionIsReadOnly);
}

void IList.RemoveAt(int index)
{
throw new NotSupportedException(SR.CheckedListBoxCheckedIndexCollectionIsReadOnly);
Expand Down Expand Up @@ -1222,6 +1254,8 @@ public void CopyTo(Array dest, int index)
}
}

void ICollection<int>.CopyTo(int[] array, int index) => CopyTo(array, index);

/// <summary>
/// This is the item array that stores our data. We share this backing store
/// with the main object collection.
Expand All @@ -1234,11 +1268,13 @@ private ItemArray InnerArray
}
}

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

public IEnumerator<int> GetEnumerator()
{
int[] indices = new int[Count];
CopyTo(indices, 0);
return indices.GetEnumerator();
return WindowsFormsUtils.GetArrayEnumerator(indices);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Getting the generic IEnumerator<> from an array requires casting the array, going through a helper function to avoid getting the cast wrong. If you prefer inlined casts I can of course remove this helper function.

}

public int IndexOf(int index)
Expand All @@ -1264,7 +1300,7 @@ int IList.IndexOf(object index)
}
}

public class CheckedItemCollection : IList
public class CheckedItemCollection : IList, IList<object>
{
internal static int CheckedItemMask = ItemArray.CreateMask();
internal static int IndeterminateItemMask = ItemArray.CreateMask();
Expand Down Expand Up @@ -1364,26 +1400,51 @@ internal int IndexOfIdentifier(object item)
return InnerArray.IndexOfIdentifier(item, AnyMask);
}

void ICollection<object>.Add(object value)
{
throw new NotSupportedException(SR.CheckedListBoxCheckedItemCollectionIsReadOnly);
}

int IList.Add(object value)
{
throw new NotSupportedException(SR.CheckedListBoxCheckedItemCollectionIsReadOnly);
}

void ICollection<object>.Clear()
{
throw new NotSupportedException(SR.CheckedListBoxCheckedItemCollectionIsReadOnly);
}

void IList.Clear()
{
throw new NotSupportedException(SR.CheckedListBoxCheckedItemCollectionIsReadOnly);
}

void IList<object>.Insert(int index, object value)
{
throw new NotSupportedException(SR.CheckedListBoxCheckedItemCollectionIsReadOnly);
}

void IList.Insert(int index, object value)
{
throw new NotSupportedException(SR.CheckedListBoxCheckedItemCollectionIsReadOnly);
}

bool ICollection<object>.Remove(object value)
{
throw new NotSupportedException(SR.CheckedListBoxCheckedItemCollectionIsReadOnly);
}

void IList.Remove(object value)
{
throw new NotSupportedException(SR.CheckedListBoxCheckedItemCollectionIsReadOnly);
}

void IList<object>.RemoveAt(int index)
{
throw new NotSupportedException(SR.CheckedListBoxCheckedItemCollectionIsReadOnly);
}

void IList.RemoveAt(int index)
{
throw new NotSupportedException(SR.CheckedListBoxCheckedItemCollectionIsReadOnly);
Expand All @@ -1398,6 +1459,8 @@ public void CopyTo(Array dest, int index)
}
}

void ICollection<object>.CopyTo(object[] dest, int index) => CopyTo(dest, index);

/// <summary>
/// This method returns if the actual item index is checked. The index is the index to the MAIN
/// collection, not this one.
Expand All @@ -1419,7 +1482,9 @@ internal CheckState GetCheckedState(int index)
return CheckState.Unchecked;
}

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

public IEnumerator<object> GetEnumerator()
{
return InnerArray.GetEnumerator(AnyMask, true);
}
Expand Down
Loading