Is there something similar to singletonList in C#
To answer your question, no. Sadly there is nothing built in, although it would often be useful when working with IEnumerable. You'll have to roll your own.
Update
Instead of using workarounds, here's an example of an efficient and immutable SingletonList that implements IList<T>
:
Usage
SingletonList<int> bling = new SingletonList<int>(10);
Code
public class SingletonList<T> : IList<T>
{
private readonly T _item;
public SingletonList(T item)
{
_item = item;
}
public IEnumerator<T> GetEnumerator()
{
yield return _item;
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
public void Add(T item)
{
throw new NotSupportedException("Add not supported.");
}
public void Clear()
{
throw new NotSupportedException("Clear not supported.");
}
public bool Contains(T item)
{
if (item == null) return _item == null;
return item.Equals(_item);
}
public void CopyTo(T[] array, int arrayIndex)
{
if (array == null) throw new ArgumentNullException("array");
array[arrayIndex] = _item;
}
public bool Remove(T item)
{
throw new NotSupportedException("Remove not supported.");
}
public int Count
{
get { return 1; }
}
public bool IsReadOnly
{
get { return true; }
}
public int IndexOf(T item)
{
return Contains(item) ? 0 : -1;
}
public void Insert(int index, T item)
{
throw new NotSupportedException("Insert not supported.");
}
public void RemoveAt(int index)
{
throw new NotSupportedException("RemoveAt not supported.");
}
public T this[int index]
{
get
{
if (index == 0) return _item;
throw new IndexOutOfRangeException();
}
set { throw new NotSupportedException("Set not supported."); }
}
}
IEnumerable<T> enumerable = Enumerable.Repeat(t, 1);
Creates an IEnumerable with one element.
Array
implements IList
; and the length cannot be modified via Add
(as ReadOnly
is true
).
Thus, SingletonList<int>
could be implemented as easily as:
var slist = new int[] { 5 };
You may want to wrap it in a System.Collections.ObjectModel.ReadOnlyCollection<T>
so that the single value cannot be changed (if the Java Singleton list works like this). E.g.
var slist = new System.Collections.ObjectModel.ReadOnlyCollection<int>(new int[] { 5 });
You can also create an extension method.
public static IList<T> AsSingletonList<T>(this IEnumerable<T> source)
{
foreach (var item in source)
{
return new System.Collections.ObjectModel.ReadOnlyCollection<T>(new T[] { item });
}
return new System.Collections.ObjectModel.ReadOnlyCollection<T>(new T[] { default(T) });
}
Or one that asserts there is exactly one value in the source:
public static IList<T> AsSingletonList<T>(this IEnumerable<T> source)
{
IList<T> result = null;
foreach (var item in source)
{
if (result != null)
throw new ArgumentOutOfRangeException("source", "Source had more than one value.");
result = new System.Collections.ObjectModel.ReadOnlyCollection<T>(new T[] { item });
}
if (result == null)
throw new ArgumentOutOfRangeException("source", "Source had no values.");
return result;
}
Edit: Used ReadOnlyCollection<T>
to prevent mutation of the single value.
Note: While I think the other answers are correct, the List<T>
by default has a capacity of 10 - which is a tiny bit wasteful.