Java has Collections.singletonList(T) which returns a List<T> of exactly one element. Is there something similar in C# that returns an IList?
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.
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."); }
}
}
public static class IListExtensions
{
public static IList<T> SingletonList<T>(this IList<T> iList, T item)
{
return Enumerable.Range(0, 1).Select(i => item).ToList().AsReadOnly();
// or
var Result = new List<T>();
Result.Add(item);
return Result.AsReadOnly();
}
}
In C#, you can use a list initializer with one element:
var x = new List<int> { 3 };
Contrary to singletonList, this list is mutable. If you want something immutable, you can call AsReadOnly() on the resulting object:
// Looks strange, but, yes, this is actually valid C#.
var x = new List<int> { 3 }.AsReadOnly();
This is a first for me: I am submitting an answer ... what I have to say does not lead itself to a comment, imho ... to a question which I think I do not fully understand ... in order to better understand the question. Consider:
public class singletonList<T> : List<T>
{
public singletonList(T theValue) { base.Add(theValue); }
public new void Add(T anotherValue) {}
public new void AddRange(T anotherValue) {}
public new void Clear() {}
public new void Insert(int index, T anotherValue) {}
public new void ToArray() {}
}
This will create a new List of whatever Type which allows only one instance of its value-Type to exist inside the List. Obviously it's not fully 'fleshed-out' since you could still use 'InsertRange' and other List altering commands.
Here's a test verifying its 'immutable' for the internal List operators masked-out by the use of 'new' in their declarations.
var q = new singletonList<int>(99);
q.Add(100);
q.Clear();
q.Insert(0, 788);
I doubt this is what the OP wants, but I am curious if this perhaps does, meet the OP's spec in any way.
In spite of ChibaCity's kind explanations, I am still utterly baffled why one would ever want to use a List that contained only one element.
Thanks in advance for educating me, and if the cost of enlightenment is loss of votes, or face ... no problem; at my age I am not running for anything except staying in place, and face is best forgotten :)
I passed a new[] { alreadyDeclaredVariable } into the function. That's one way to do it, just making an in-place array of 1 element.
Related
I'm writing an application where I am required to use Reflection to call a method which has parameters of type MyObject.
Method (List<MyObject> input , out List<MyObject> output,..... );
Using reflection I send the parameter of type Object. How can I cast List<MyObject> to List<object>
var parameters = new Object[] { inputs, outputs, userPrams };
System.Type classType = typeof(MyClass);
object instance = Activator.CreateInstance(classType);
classType.InvokeMember(name, BindingFlags.InvokeMethod | BindingFlags.Instance | BindingFlags.Public,null, instance, parameters);
In the code above both input and output are lists of type MyObject
I tried to Cast them to List of Objects but this doesn't work
x.Outputs = grOutputs as IList<object>
Can anyone help?
Your question is not 100% clear, so I assumed the problem you're facing is the one you put in the title:
Cast List of MyType to List of objects
As #Charles said, IList<T> and List<T> are not variant, so you can't cast IList<DerivedClass> to IList<BaseClass>. You have to create new List<BaseClass>.
There are many ways to do that, I think there are two you should consider:
You can use Cast and ToList, but it will require using System.Linq.
var listOfStrings = new List<string>() { "foo", "bar" };
var listOfObjects = listOfStrings.Cast<object>().ToList();
To avoid that, you can use new List<T>(IEnumerable<T> source) constructor. Because IEnumerable<T> is covariant, you can do following:
var listOfStrings = new List<string>() { "foo", "bar" };
var listOfObjects = new List<object>(listOfString);
You might well want to do something like this:
var dogs = new List<Dog>();
var pets = (List<object>)dogs;
pets.Add(new Cat());
The C# language is heavily invested in you stop mixing cats and dogs like this. It violates the hard guarantee that the list only ever contains dogs. You'll have to do it like this instead:
var dogs = new List<Dog>();
var pets = new List<object>(dogs);
pets.Add(new Cat());
Which is fine, it creates a new list, one that no longer guarantees that it only ever contains dogs since it only promises that the list contains object. Pretty useless, typically, you basically lose all knowledge of what the list contains. Forcing you to write hunt-the-fox code that uses the as operator or Reflection to find the proper animal back. Code that fails to do its job at run-time instead of the compiler telling you that its wrong code at build time, when you're still in the comfortable cubicle cocoon.
Which it did.
IList<T> is not covariant, you would need to create a new list if you wanted IList<object>:
x.Outputs = grOutputs.Cast<object>().ToList();
If I understand your question, you could try something like this :
var objList = myClassList.OfType<object>();
You cannot make your desired cast because, as others have written, collections in c# are not covariant.
You can either create a new list, or introduce a ListWrapper class like so:
public class ListWrapper<TOut, TIn> : IList<TOut> where TIn : class, TOut where TOut : class
{
readonly IList<TIn> list;
public ListWrapper(IList<TIn> list)
{
if (list == null)
throw new NullReferenceException();
this.list = list;
}
#region IList<TOut> Members
public int IndexOf(TOut item)
{
TIn itemIn = item as TIn;
if (itemIn != item)
return -1;
return list.IndexOf(itemIn);
}
public void Insert(int index, TOut item)
{
list.Insert(index, (TIn)item);
}
public void RemoveAt(int index)
{
list.RemoveAt(index);
}
public TOut this[int index]
{
get
{
return list[index];
}
set
{
list[index] = (TIn)value;
}
}
#endregion
#region ICollection<TOut> Members
public void Add(TOut item)
{
list.Add((TIn)item);
}
public void Clear()
{
list.Clear();
}
public bool Contains(TOut item)
{
TIn itemIn = item as TIn;
if (itemIn != item)
return false;
return list.Contains(itemIn);
}
public void CopyTo(TOut[] array, int arrayIndex)
{
foreach (var item in list)
{
array[arrayIndex] = item;
arrayIndex++;
}
}
public int Count
{
get { return list.Count; }
}
public bool IsReadOnly
{
get
{
return list.IsReadOnly;
}
}
public bool Remove(TOut item)
{
return list.Remove(item as TIn);
}
#endregion
#region IEnumerable<TOut> Members
public IEnumerator<TOut> GetEnumerator()
{
foreach (var item in list)
yield return item;
}
#endregion
#region IEnumerable Members
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
#endregion
}
You might want to make the wrapper read-only since the setter could throw an exception if the incoming object is not of the inner list's item type.
In the following code, is the Select() method smart enough to keep the size of the list somewhere internally for the ToArray() method to be cheap?
List<Thing> bigList = someBigList;
var bigArray = bigList.Select(t => t.SomeField).ToArray();
That's easy to check, without looking at the implementation. Just create a class that implements IList<T>, and put a trace in the Count property:
class MyList<T> : IList<T>
{
private readonly IList<T> _list = new List<T>();
public IEnumerator<T> GetEnumerator()
{
return _list.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
{
Console.WriteLine ("Count accessed");
return _list.Count;
}
}
public bool IsReadOnly
{
get { return _list.IsReadOnly; }
}
public int IndexOf(T item)
{
return _list.IndexOf(item);
}
public void Insert(int index, T item)
{
_list.Insert(index, item);
}
public void RemoveAt(int index)
{
_list.RemoveAt(index);
}
public T this[int index]
{
get { return _list[index]; }
set { _list[index] = value; }
}
#region Implementation of IEnumerable
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
#endregion
}
If the Count property is accessed, this code should print "Count accessed":
var list = new MyList<int> { 1, 2, 3 };
var array = list.Select(x => x).ToArray();
But it doesn't print anything, so no, it doesn't keep track of the count. Of course there could be an optimization specific to List<T>, but it seems unlikely...
No, right now it does not (at least the .NET implementation). From the MS reference sources, Enumerable.ToArray is implemented as
public static TSource[] ToArray<TSource>(this IEnumerable<TSource> source) {
if (source == null) throw Error.ArgumentNull("source");
return new Buffer<TSource>(source).ToArray();
}
Buffer<TSource> creates a copy of the source sequence (in array form) on construction by iterating and resizing as necessary; it has a special "fast path" if source is an ICollection<TSource>, but the result of Enumerable.Select unsurprisingly does not implement that interface.
Be that as it may, apart from pure curiosity I don't think that this result means anything. For one, the implementation may change at any point in the future (even though a quick cost-benefit analysis won't find this likely). And in any case, you will suffer at most O(logN) reallocations. For small N the reallocations are not going to be noticeable. For large N, the amount of time spent on iterating over the collection is going to be O(N) and will therefore easily dominate.
When you apply Select operator to enumerable sequence, it creates one of following iterators:
WhereSelectArrayIterator
WhereSelectListIterator
WhereSelectEnumerableIterator
In case of List<T>, WhereSelectListIterator iterator is created. It uses list's iterator to iterate over the list and apply predicate and selector. This is a MoveNext method implementation:
while (this.enumerator.MoveNext())
{
TSource current = this.enumerator.Current;
if ((this.predicate == null) || this.predicate(current))
{
base.current = this.selector(current);
return true;
}
}
As you can see, it does not preserve information about number of items, which matched predicate, thus it does not know count of items in filtered sequence.
I have a DataSource in my control which is always a List<T> where T has to inherit from IEntity.
public class MyClass<T> where T : IEntity
{
public List<T> DataSource
{
get;
set;
}
}
Now, obviously you can't cast a List<T> to a List<IEntity> doing the following:
List<IEntity> wontWork = (List<IEntity>)this.DataSource;
How can I get the DataSource as a List of IEntity, whilst still being able to add and remove items from the DataSource? I.e. I could do the following, but removing from the List it returns would not remove from the DataSource:
public List<TOut> GetDataSourceCopyAsUnderlyingType<TOut>()
{
if (this.DataSource == null)
{
return new List<TOut>();
}
else
{
// Get the list and the enumerator
IList list = (IList)this.DataSource;
IEnumerator enumerator = list.GetEnumerator();
// Build the target list
List<TOut> targetList = new List<TOut>();
int i = 0;
while (enumerator.MoveNext())
{
TOut entity = (TOut)list[i];
targetList.Add(entity);
i++;
}
return targetList;
}
}
Basically, I need some way of doing the following:
List<IEntity> interfaceList = this.GetDataSourceAsAnotherType<IEntity>();
int dataSourceCount = this.DataSource.Count; // Equals 5
int interfaceCount = interfaceList.Count; // Equals 5
interfaceList.RemoveAt(0);
int dataSourceCount = this.DataSource.Count; // Equals 4
int interfaceCount = interfaceList.Count; // Equals 4
And just to add, I don't mind if it means I've got to use a different type instead of a List.
EDIT: Sorry, forgot to say I'm using .Net2.0 and cannot move to .Net 3.5.
It would be a monumentally bad idea if this were allowed, which is why it isn't. I can add any old IEntity to a List<IEntity> which will blow up if that IEntity can't be cast to T. Whilst all Ts are IEntities, not all IEntities are Ts.
This works with arrays because arrays have a deliberate subtyping hole (as they do in Java). Collections do not have a subtyping hole.
Create a wrapper class that seamlessly converts. Untested sample:
public class CastList<TTarget, TOriginal>
: IList<TTarget> where TOriginal : TTarget
{
List<TOriginal> _orig;
public CastList(List<TOriginal> orig) { _orig = orig; }
public Add(TTarget item) { _orig.Add(item); }
public TTarget this[int i]
{
get { return (TTarget)_orig[i]; }
set { _orig[i] = value; }
}
public IEnumerator<TTarget> GetEnumerator()
{
foreach(TOriginal item in _orig)
yield return (TTarget)item;
}
// etc...
}
Manipulations of the original list will also be reflected in the wrapper. To use this, just construct it with your DataSource.
What DrPizza said, but with more code:
public class ListFacade<TIn, TOut> : IList<TOut> where TIn : TOut
{
private readonly IList<TIn> innerList;
public ListFacade(IList<TIn> innerList)
{
this.innerList = innerList;
}
public int Count
{
get { return this.innerList.Count; }
}
public bool IsReadOnly
{
get { return this.innerList.IsReadOnly; }
}
public TOut this[int index]
{
get { return this.innerList[index]; }
set { this.innerList[index] = (TIn)value; }
}
public void Add(TOut item)
{
this.innerList.Add((TIn)item);
}
public void Clear()
{
this.innerList.Clear();
}
public bool Contains(TOut item)
{
return (item is TIn) && this.innerList.Contains((TIn)item);
}
public void CopyTo(TOut[] array, int arrayIndex)
{
var inArray = new TIn[this.innerList.Count];
this.innerList.CopyTo(inArray, arrayIndex);
Array.Copy(inArray, array, inArray.Length);
}
public IEnumerator<TOut> GetEnumerator()
{
foreach (var item in this.innerList)
{
yield return item;
}
}
System.Collections.IEnumerator
System.Collections.IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
public int IndexOf(TOut item)
{
return (item is TIn) ? this.innerList.IndexOf((TIn)item) : -1;
}
public void Insert(int index, TOut item)
{
this.innerList.Insert(index, (TIn)item);
}
public bool Remove(TOut item)
{
return (item is TIn) && this.innerList.Remove((TIn)item);
}
public void RemoveAt(int index)
{
this.innerList.RemoveAt(index);
}
Add, Insert and the indexer set will blow up if the argument is not of type TIn.
ok this might be completely beside the point but, how about using a little bit of Linq?
var interfaceList = objectList.ConvertAll<Interface>(o => (Interface)o);
this way you can cast the objectList easily.
hope this helps to find the solution...
I'm in favor of linq too, but you can do it like:
var interfaceList = objectList.Cast<IEntity>();
Which is shorter and more expressive.
Is there a built-in way to convert IEnumerator<T> to IEnumerable<T>?
The easiest way of converting I can think of is via the yield statement
public static IEnumerable<T> ToIEnumerable<T>(this IEnumerator<T> enumerator) {
while ( enumerator.MoveNext() ) {
yield return enumerator.Current;
}
}
compared to the list version this has the advantage of not enumerating the entire list before returning an IEnumerable. using the yield statement you'd only iterate over the items you need, whereas using the list version, you'd first iterate over all items in the list and then all the items you need.
for a little more fun you could change it to
public static IEnumerable<K> Select<K,T>(this IEnumerator<T> e,
Func<K,T> selector) {
while ( e.MoveNext() ) {
yield return selector(e.Current);
}
}
you'd then be able to use linq on your enumerator like:
IEnumerator<T> enumerator;
var someList = from item in enumerator
select new classThatTakesTInConstructor(item);
You could use the following which will kinda work.
public class FakeEnumerable<T> : IEnumerable<T> {
private IEnumerator<T> m_enumerator;
public FakeEnumerable(IEnumerator<T> e) {
m_enumerator = e;
}
public IEnumerator<T> GetEnumerator() {
return m_enumerator;
}
// Rest omitted
}
This will get you into trouble though when people expect successive calls to GetEnumerator to return different enumerators vs. the same one. But if it's a one time only use in a very constrained scenario, this could unblock you.
I do suggest though you try and not do this because I think eventually it will come back to haunt you.
A safer option is along the lines Jonathan suggested. You can expend the enumerator and create a List<T> of the remaining items.
public static List<T> SaveRest<T>(this IEnumerator<T> e) {
var list = new List<T>();
while ( e.MoveNext() ) {
list.Add(e.Current);
}
return list;
}
EnumeratorEnumerable<T>
A threadsafe, resettable adaptor from IEnumerator<T> to IEnumerable<T>
I use Enumerator parameters like in C++ forward_iterator concept.
I agree that this can lead to confusion as too many people will indeed assume Enumerators are /like/ Enumerables, but they are not.
However, the confusion is fed by the fact that IEnumerator contains the Reset method. Here is my idea of the most correct implementation. It leverages the implementation of IEnumerator.Reset()
A major difference between an Enumerable and and Enumerator is, that an Enumerable might be able to create several Enumerators simultaneously. This implementation puts a whole lot of work into making sure that this never happens for the EnumeratorEnumerable<T> type. There are two EnumeratorEnumerableModes:
Blocking (meaning that a second caller will simply wait till the first enumeration is completed)
NonBlocking (meaning that a second (concurrent) request for an enumerator simply throws an exception)
Note 1: 74 lines are implementation, 79 lines are testing code :)
Note 2: I didn't refer to any unit testing framework for SO convenience
using System;
using System.Diagnostics;
using System.Linq;
using System.Collections;
using System.Collections.Generic;
using System.Threading;
namespace EnumeratorTests
{
public enum EnumeratorEnumerableMode
{
NonBlocking,
Blocking,
}
public sealed class EnumeratorEnumerable<T> : IEnumerable<T>
{
#region LockingEnumWrapper
public sealed class LockingEnumWrapper : IEnumerator<T>
{
private static readonly HashSet<IEnumerator<T>> BusyTable = new HashSet<IEnumerator<T>>();
private readonly IEnumerator<T> _wrap;
internal LockingEnumWrapper(IEnumerator<T> wrap, EnumeratorEnumerableMode allowBlocking)
{
_wrap = wrap;
if (allowBlocking == EnumeratorEnumerableMode.Blocking)
Monitor.Enter(_wrap);
else if (!Monitor.TryEnter(_wrap))
throw new InvalidOperationException("Thread conflict accessing busy Enumerator") {Source = "LockingEnumWrapper"};
lock (BusyTable)
{
if (BusyTable.Contains(_wrap))
throw new LockRecursionException("Self lock (deadlock) conflict accessing busy Enumerator") { Source = "LockingEnumWrapper" };
BusyTable.Add(_wrap);
}
// always implicit Reset
_wrap.Reset();
}
#region Implementation of IDisposable and IEnumerator
public void Dispose()
{
lock (BusyTable)
BusyTable.Remove(_wrap);
Monitor.Exit(_wrap);
}
public bool MoveNext() { return _wrap.MoveNext(); }
public void Reset() { _wrap.Reset(); }
public T Current { get { return _wrap.Current; } }
object IEnumerator.Current { get { return Current; } }
#endregion
}
#endregion
private readonly IEnumerator<T> _enumerator;
private readonly EnumeratorEnumerableMode _allowBlocking;
public EnumeratorEnumerable(IEnumerator<T> e, EnumeratorEnumerableMode allowBlocking)
{
_enumerator = e;
_allowBlocking = allowBlocking;
}
private LockRecursionPolicy a;
public IEnumerator<T> GetEnumerator()
{
return new LockingEnumWrapper(_enumerator, _allowBlocking);
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
class TestClass
{
private static readonly string World = "hello world\n";
public static void Main(string[] args)
{
var master = World.GetEnumerator();
var nonblocking = new EnumeratorEnumerable<char>(master, EnumeratorEnumerableMode.NonBlocking);
var blocking = new EnumeratorEnumerable<char>(master, EnumeratorEnumerableMode.Blocking);
foreach (var c in nonblocking) Console.Write(c); // OK (implicit Reset())
foreach (var c in blocking) Console.Write(c); // OK (implicit Reset())
foreach (var c in nonblocking) Console.Write(c); // OK (implicit Reset())
foreach (var c in blocking) Console.Write(c); // OK (implicit Reset())
try
{
var willRaiseException = from c1 in nonblocking from c2 in nonblocking select new {c1, c2};
Console.WriteLine("Cartesian product: {0}", willRaiseException.Count()); // RAISE
}
catch (Exception e) { Console.WriteLine(e); }
foreach (var c in nonblocking) Console.Write(c); // OK (implicit Reset())
foreach (var c in blocking) Console.Write(c); // OK (implicit Reset())
try
{
var willSelfLock = from c1 in blocking from c2 in blocking select new { c1, c2 };
Console.WriteLine("Cartesian product: {0}", willSelfLock.Count()); // LOCK
}
catch (Exception e) { Console.WriteLine(e); }
// should not externally throw (exceptions on other threads reported to console)
if (ThreadConflictCombinations(blocking, nonblocking))
throw new InvalidOperationException("Should have thrown an exception on background thread");
if (ThreadConflictCombinations(nonblocking, nonblocking))
throw new InvalidOperationException("Should have thrown an exception on background thread");
if (ThreadConflictCombinations(nonblocking, blocking))
Console.WriteLine("Background thread timed out");
if (ThreadConflictCombinations(blocking, blocking))
Console.WriteLine("Background thread timed out");
Debug.Assert(true); // Must be reached
}
private static bool ThreadConflictCombinations(IEnumerable<char> main, IEnumerable<char> other)
{
try
{
using (main.GetEnumerator())
{
var bg = new Thread(o =>
{
try { other.GetEnumerator(); }
catch (Exception e) { Report(e); }
}) { Name = "background" };
bg.Start();
bool timedOut = !bg.Join(1000); // observe the thread waiting a full second for a lock (or throw the exception for nonblocking)
if (timedOut)
bg.Abort();
return timedOut;
}
} catch
{
throw new InvalidProgramException("Cannot be reached");
}
}
static private readonly object ConsoleSynch = new Object();
private static void Report(Exception e)
{
lock (ConsoleSynch)
Console.WriteLine("Thread:{0}\tException:{1}", Thread.CurrentThread.Name, e);
}
}
}
Note 3: I think the implementation of the thread locking (especially around BusyTable) is quite ugly; However, I didn't want to resort to ReaderWriterLock(LockRecursionPolicy.NoRecursion) and didn't want to assume .Net 4.0 for SpinLock
Solution with use of Factory along with fixing cached IEnumerator issue in JaredPar's answer allows to change the way of enumeration.
Consider a simple example: we want custom List<T> wrapper that allow to enumerate in reverse order along with default enumeration. List<T> already implements IEnumerator for default enumeration, we only need to create IEnumerator that enumerates in reverse order. (We won't use List<T>.AsEnumerable().Reverse() because it enumerates the list twice)
public enum EnumerationType {
Default = 0,
Reverse
}
public class CustomList<T> : IEnumerable<T> {
private readonly List<T> list;
public CustomList(IEnumerable<T> list) => this.list = new List<T>(list);
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
//Default IEnumerable method will return default enumerator factory
public IEnumerator<T> GetEnumerator()
=> GetEnumerable(EnumerationType.Default).GetEnumerator();
public IEnumerable<T> GetEnumerable(EnumerationType enumerationType)
=> enumerationType switch {
EnumerationType.Default => new DefaultEnumeratorFactory(list),
EnumerationType.Reverse => new ReverseEnumeratorFactory(list)
};
//Simple implementation of reverse list enumerator
private class ReverseEnumerator : IEnumerator<T> {
private readonly List<T> list;
private int index;
internal ReverseEnumerator(List<T> list) {
this.list = list;
index = list.Count-1;
Current = default;
}
public void Dispose() { }
public bool MoveNext() {
if(index >= 0) {
Current = list[index];
index--;
return true;
}
Current = default;
return false;
}
public T Current { get; private set; }
object IEnumerator.Current => Current;
void IEnumerator.Reset() {
index = list.Count - 1;
Current = default;
}
}
private abstract class EnumeratorFactory : IEnumerable<T> {
protected readonly List<T> List;
protected EnumeratorFactory(List<T> list) => List = list;
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
public abstract IEnumerator<T> GetEnumerator();
}
private class DefaultEnumeratorFactory : EnumeratorFactory {
public DefaultEnumeratorFactory(List<T> list) : base(list) { }
//Default enumerator is already implemented in List<T>
public override IEnumerator<T> GetEnumerator() => List.GetEnumerator();
}
private class ReverseEnumeratorFactory : EnumeratorFactory {
public ReverseEnumeratorFactory(List<T> list) : base(list) { }
public override IEnumerator<T> GetEnumerator() => new ReverseEnumerator(List);
}
}
As Jason Watts said -- no, not directly.
If you really want to, you could loop through the IEnumerator<T>, putting the items into a List<T>, and return that, but I'm guessing that's not what you're looking to do.
The basic reason you can't go that direction (IEnumerator<T> to a IEnumerable<T>) is that IEnumerable<T> represents a set that can be enumerated, but IEnumerator<T> is a specific enumeratation over a set of items -- you can't turn the specific instance back into the thing that created it.
static class Helper
{
public static List<T> SaveRest<T>(this IEnumerator<T> enumerator)
{
var list = new List<T>();
while (enumerator.MoveNext())
{
list.Add(enumerator.Current);
}
return list;
}
public static ArrayList SaveRest(this IEnumerator enumerator)
{
var list = new ArrayList();
while (enumerator.MoveNext())
{
list.Add(enumerator.Current);
}
return list;
}
}
Nope, IEnumerator<> and IEnumerable<> are different beasts entirely.
This is a variant I have written... The specific is a little different. I wanted to do a MoveNext() on an IEnumerable<T>, check the result, and then roll everything in a new IEnumerator<T> that was "complete" (so that included even the element of the IEnumerable<T> I had already extracted)
// Simple IEnumerable<T> that "uses" an IEnumerator<T> that has
// already received a MoveNext(). "eats" the first MoveNext()
// received, then continues normally. For shortness, both IEnumerable<T>
// and IEnumerator<T> are implemented by the same class. Note that if a
// second call to GetEnumerator() is done, the "real" IEnumerator<T> will
// be returned, not this proxy implementation.
public class EnumerableFromStartedEnumerator<T> : IEnumerable<T>, IEnumerator<T>
{
public readonly IEnumerator<T> Enumerator;
public readonly IEnumerable<T> Enumerable;
// Received by creator. Return value of MoveNext() done by caller
protected bool FirstMoveNextSuccessful { get; set; }
// The Enumerator can be "used" only once, then a new enumerator
// can be requested by Enumerable.GetEnumerator()
// (default = false)
protected bool Used { get; set; }
// The first MoveNext() has been already done (default = false)
protected bool DoneMoveNext { get; set; }
public EnumerableFromStartedEnumerator(IEnumerator<T> enumerator, bool firstMoveNextSuccessful, IEnumerable<T> enumerable)
{
Enumerator = enumerator;
FirstMoveNextSuccessful = firstMoveNextSuccessful;
Enumerable = enumerable;
}
public IEnumerator<T> GetEnumerator()
{
if (Used)
{
return Enumerable.GetEnumerator();
}
Used = true;
return this;
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
public T Current
{
get
{
// There are various school of though on what should
// happens if called before the first MoveNext() or
// after a MoveNext() returns false. We follow the
// "return default(TInner)" school of thought for the
// before first MoveNext() and the "whatever the
// Enumerator wants" for the after a MoveNext() returns
// false
if (!DoneMoveNext)
{
return default(T);
}
return Enumerator.Current;
}
}
public void Dispose()
{
Enumerator.Dispose();
}
object IEnumerator.Current
{
get
{
return Current;
}
}
public bool MoveNext()
{
if (!DoneMoveNext)
{
DoneMoveNext = true;
return FirstMoveNextSuccessful;
}
return Enumerator.MoveNext();
}
public void Reset()
{
// This will 99% throw :-) Not our problem.
Enumerator.Reset();
// So it is improbable we will arrive here
DoneMoveNext = true;
}
}
Use:
var enumerable = someCollection<T>;
var enumerator = enumerable.GetEnumerator();
bool res = enumerator.MoveNext();
// do whatever you want with res/enumerator.Current
var enumerable2 = new EnumerableFromStartedEnumerator<T>(enumerator, res, enumerable);
Now, the first GetEnumerator() that will be requested to enumerable2 will be given through the enumerator enumerator. From the second onward the enumerable.GetEnumerator() will be used.
The other answers here are ... strange. IEnumerable<T> has just one method, GetEnumerator(). And an IEnumerable<T> must implement IEnumerable, which also has just one method, GetEnumerator() (the difference being that one is generic on T and the other is not). So it should be clear how to turn an IEnumerator<T> into an IEnumerable<T>:
// using modern expression-body syntax
public class IEnumeratorToIEnumerable<T> : IEnumerable<T>
{
private readonly IEnumerator<T> Enumerator;
public IEnumeratorToIEnumerable(IEnumerator<T> enumerator) =>
Enumerator = enumerator;
public IEnumerator<T> GetEnumerator() => Enumerator;
IEnumerator IEnumerable.GetEnumerator() => Enumerator;
}
foreach (var foo in new IEnumeratorToIEnumerable<Foo>(fooEnumerator))
DoSomethingWith(foo);
// and you can also do:
var fooEnumerable = new IEnumeratorToIEnumerable<Foo>(fooEnumerator);
foreach (var foo in fooEnumerable)
DoSomethingWith(foo);
// Some IEnumerators automatically repeat after MoveNext() returns false,
// in which case this is a no-op, but generally it's required.
fooEnumerator.Reset();
foreach (var foo in fooEnumerable)
DoSomethingElseWith(foo);
However, none of this should be needed because it's unusual to have an IEnumerator<T> that doesn't come with an IEnumerable<T> that returns an instance of it from its GetEnumerator method. If you're writing your own IEnumerator<T>, you should certainly provide the IEnumerable<T>. And really it's the other way around ... an IEnumerator<T> is intended to be a private class that iterates over instances of a public class that implements IEnumerable<T>.
I need to sort some objects according to their contents (in fact according to one of their properties, which is NOT the key and may be duplicated between different objects).
.NET provides two classes (SortedDictionary and SortedList), and both are implemented using a binary tree. The only differences between them are
SortedList uses less memory than SortedDictionary.
SortedDictionary has faster insertion and removal operations for unsorted data, O(log n) as opposed to O(n) for SortedList.
If the list is populated all at once from sorted data, SortedList is faster than SortedDictionary.
I could achieve what I want using a List, and then using its Sort() method with a custom implementation of IComparer, but it would not be time-efficient as I would sort the whole List each time I want to insert a new object, whereas a good SortedList would just insert the item at the right position.
What I need is a SortedList class with a RefreshPosition(int index) to move only the changed (or inserted) object rather than resorting the whole list each time an object inside changes.
Am I missing something obvious ?
Maybe I'm slow, but isn't this the easiest implementation ever?
class SortedList<T> : List<T>
{
public new void Add(T item)
{
Insert(~BinarySearch(item), item);
}
}
http://msdn.microsoft.com/en-us/library/w4e7fxsh.aspx
Unfortunately, Add wasn't overrideable so I had to new it which isn't so nice when you have List<T> list = new SortedList<T>; which I actually needed to do.... so I went ahead and rebuilt the whole thing...
class SortedList<T> : IList<T>
{
private List<T> list = new List<T>();
public int IndexOf(T item)
{
var index = list.BinarySearch(item);
return index < 0 ? -1 : index;
}
public void Insert(int index, T item)
{
throw new NotImplementedException("Cannot insert at index; must preserve order.");
}
public void RemoveAt(int index)
{
list.RemoveAt(index);
}
public T this[int index]
{
get
{
return list[index];
}
set
{
list.RemoveAt(index);
this.Add(value);
}
}
public void Add(T item)
{
list.Insert(~list.BinarySearch(item), item);
}
public void Clear()
{
list.Clear();
}
public bool Contains(T item)
{
return list.BinarySearch(item) >= 0;
}
public void CopyTo(T[] array, int arrayIndex)
{
list.CopyTo(array, arrayIndex);
}
public int Count
{
get { return list.Count; }
}
public bool IsReadOnly
{
get { return false; }
}
public bool Remove(T item)
{
var index = list.BinarySearch(item);
if (index < 0) return false;
list.RemoveAt(index);
return true;
}
public IEnumerator<T> GetEnumerator()
{
return list.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return list.GetEnumerator();
}
}
Or perhaps something like this is a more appropriate Remove function...
public bool Remove(T item)
{
var index = list.BinarySearch(item);
if (index < 0) return false;
while (((IComparable)item).CompareTo((IComparable)list[index]) == 0)
{
if (item == list[index])
{
list.RemoveAt(index);
return true;
}
index++;
}
return false;
}
Assuming items can compare equal but not be equal...
I eventually decided to write it :
class RealSortedList<T> : List<T>
{
public IComparer<T> comparer;
public int SortItem(int index)
{
T item = this[index];
this.RemoveAt(index);
int goodposition=FindLocation(this[index], 0, this.Count);
this.Insert(goodposition, item);
return goodposition;
}
public int FindLocation(T item, int begin, int end)
{
if (begin==end)
return begin;
int middle = begin + end / 2;
int comparisonvalue = comparer.Compare(item, this[middle]);
if (comparisonvalue < 0)
return FindLocation(item,begin, middle);
else if (comparisonvalue > 0)
return FindLocation(item,middle, end);
else
return middle;
}
}
Don't forget that inserting an item into a list backed by an array can be an expensive operation - inserting a bunch of items and then sorting may well be quicker unless you really need to sort after every single operation.
Alternatively, you could always wrap a list and make your add operation find the right place and insert it there.
I've solved this problem in the past by writing an extension method that does a binary search on a IList, and another that does an insert. You can look up the correct implementation in the CLR source because there's a built-in version that works only on arrays, and then just tweak it to be an extension on IList.
One of those "should be in the BCL already" things.
What I need is a SortedList class with
a RefreshPosition(int index) to move
only the changed (or inserted) object
rather than resorting the whole list
each time an object inside changes.
Why would you update using an index when such updates invalidate the index? Really, I would think that updating by object reference would be more convenient. You can do this with the SortedList - just remember that your Key type is the same as the return type of the function that extracts the comparable data form the object.
class UpdateableSortedList<K,V> {
private SortedList<K,V> list = new SortedList<K,V>();
public delegate K ExtractKeyFunc(V v);
private ExtractKeyFunc func;
public UpdateableSortedList(ExtractKeyFunc f) { func = f; }
public void Add(V v) {
list[func(v)] = v;
}
public void Update(V v) {
int i = list.IndexOfValue(v);
if (i >= 0) {
list.RemoveAt(i);
}
list[func(v)] = v;
}
public IEnumerable<T> Values { get { return list.Values; } }
}
Something like that I guess.