Is there a built-in class in C # that implements a looped list function? Well, that is I need a regular list, but the last element, which refers to the first, as the next. Of course, all the functionality to add, delete, move, etc. must take the class. On the client side, something like:

var ring = new Ring<string>(); ring.Add("зима"); ring.Add("весна"); ring.Add("лето"); ring.Add("осень"); foreach(var item in ring) { var msg = string.Format("Наступила(о) {0}", item); MessageBox.Show(msg); Thread.Sleep(TimeSpan.FromMonthes(3)); } 

If there is no ready-made class, how to implement it correctly? As I understand it, I implement the interface class Ring<T> : IList<T> and add what else is needed for the intended functionality.

  • List in sharpe implies a finite collection, whereas in your case the collection will be infinite. Or I do not understand something in your terms. Adding items possible? Links to the following. elements are put down automatically or pens? - Monk
  • @Monk, clarified the question on your comment. Thank. - 4per
  • one
    Well, LinkedList can be closed, although I'm not sure that he will like it, but this is just the doubly linked list you wanted. Or you can make your own version based on it, you can peek here at referencesource.microsoft.com/System/R/df5a6c7b6b60da4f.html - rdorn
  • @rdorn, thank you so much for the example! after studying it, my life will never be the same ((: - 4per
  • are you still not looking at the source for WinForms, there is still more wonderful =) - rdorn

1 answer 1

I hope I did not miss much. A naive implementation in 5 minutes on my knee looks like this:

  public class Ring<T> : ICollection<T>, IEnumerator<T> { private List<T> list = new List<T>(); public IEnumerator<T> GetEnumerator() { return this; } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } public void Add(T item) { list.Add(item); } public void Clear() { list.Clear(); } public bool Contains(T item) { return list.Contains(item); } public void CopyTo(T[] array, int arrayIndex) { list.CopyTo(array, arrayIndex); } public bool Remove(T item) { return list.Remove(item); } public int Count { get { return list.Count; } } public bool IsReadOnly { get { return false; } } public void Dispose() { } public bool MoveNext() { if (list.Count == 0) return false; index = list.Count > index + 1 ? index + 1 : 0; Current = list[index]; return true; } public void Reset() { index = 0; } private int index = 0; public T Current { get; private set; } object IEnumerator.Current { get { return Current; } } } 

With such an implementation, your seasons revolve with a bang. Perhaps there are some problems here, but in general - something like this can be done looping through the collection in one foreach . For on such a collection will no longer drive through the cycle, because we honestly say how many elements are inside.

  • "For on such a collection will no longer drive through the cycle" - depending on what condition on the exit from for ... or does c # set any restrictions on this condition? - 4per
  • @ 4per well, yes, but it is the canonical implementation by ring.Count that is ring.Count off. It's more like while(True) should be driven then =) - Monk
  • But what about the classic for(int i = 0; ; i=(i+1)%N){ } ? Even in the usual array, it will run in circles of a given length =) - rdorn
  • @rdorn for any conditions you can write, here I agree with you. Yes, and my version of the ring is clearly designed only for foreach . - Monk
  • Why only foreach, you can get a copy of the array and run on it as you like. Another question is that the classic bidirectional list implies the possibility of going in both directions, so it’s probably worth doing separate LR and RL enumerators, but this is more a question for the author than for you. - rdorn