How to add new constructor that will not break OOP principle? - c#

I have a wrapper class to work with IAsyncCursor that returns IEnumerable<TResult>
My program can take items from two places:
IEnumerable<TResult> GetItems()
{
List<TResult> fromA = fromA();
IEnumerable<TResult> fromB = fromB();
var result = fromA.Concat(fromB).ToList();
return result;
}
But I don't want to store the result in memory because its too expensive.
I would like to change my return result of GetItems() to returns ResultCollection and have the ability to call Dispose()
So, I need to change the result from fromA() and fromB() methods to returns ResultCollection, like the following
ResultCollection<TResult> GetItems()
{
ResultCollection<TResult> fromA = fromA(); // wrap List<TResult> to ResultCollection
ResultCollection<TResult> fromB = fromB(); // return collection that I can dispose when I need
return new ResultCollection<TResult>(fromA.Concat(fromB).ToList());
}
How do I need to change my ResultCollection to store List constructor? I need that this new class correspond all OOP and SOLID principle.
I don't need to have just another constructor inside ResultCollection like this
public ResultCollection(IList<TResult> list)
{
_list = list;
}

GetItems should not return a DeferredResultCollection. It should return IEnumerable<...>. And then you can just do
return fromA.Concat(fromB);
Which will be completely lazy.
The whole class DeferredResultCollection should never be exposed to consumers of this API because it has no useful public members. IEnumerable<...> is totally enough.
In fact, the class DeferredResultCollection is not needed at all. You could replace it with an iterator.
Here's a fleshed out version:
Delete DeferredResultCollection
Use this:
.
public static IEnumerable<TResult> CreateDeferredIEnumerable(IAsyncCursor<TResult> _asyncCursor)
{
if (_asyncCursor != null)
{
using (_asyncCursor) { //This is key
for (; _asyncCursor.MoveNextAsync().Result;)
{
foreach (var result in _asyncCursor.Current)
{
yield return result;
}
}
} //The Dispose is always triggered!
}
}
This always disposes resources, even in these sample cases:
1. ((IDisposable)CreateDeferredIEnumerable(...)).Dispose();
1. ((IDisposable)CreateDeferredIEnumerable(...).GetEnumerator()).Dispose();
2. CreateDeferredIEnumerable(...).ToList();
3. CreateDeferredIEnumerable(...).Take(1).ToList();
4. foreach (var x in CreateDeferredIEnumerable(...)) break;
In order to support concat we need to ensure disposal:
tatic IEnumerable<TSource> ConcatIterator<TSource>(IEnumerable<TSource> first, IEnumerable<TSource> second)
{
using (first as IDisposable) {
using (secondas IDisposable) {
foreach (TSource iteratorVariable0 in first)
{
yield return iteratorVariable0;
}
foreach (TSource iteratorVariable1 in second)
{
yield return iteratorVariable1;
}
}
}
}
I hope this works, it's quickly hacked together. It can be made to work for sure, though.

You can create a new interface called IDisposableEnumerable that have the following definition:
public interface IDisposableEnumerable<T> : IEnumerable<T>, IDisposable
{
}
And then make your DeferredResultCollection class implement such interface.
Then you should create another implementation of such interface that wraps any IEnumerable<T>. Such class can be called EnumerableWrapper and it does nothing inside its Dispose method.
You would also need to create another implementation that can concatinate two (or more) IDisposableEnumerable objects together using the Composite Pattern, such class can be called CompositeDisposableEnumerable.
Please note that your DeferredResultCollection class blocks when invoking asynchronous methods which is not optimal.
You might also want to consider using Reactive Extensions for .NET, but that is whole different thing that will probably cause design changes.
UPDATE:
Here is how EnumerableWrapper and CompositeDisposableEnumerable would look like:
public class EnumerableWrapper<T> : IDisposableEnumerable<T>
{
private readonly IEnumerable<T> m_Enumerable;
public EnumerableWrapper(IEnumerable<T> enumerable)
{
m_Enumerable = enumerable;
}
public void Dispose()
{
}
public IEnumerator<T> GetEnumerator()
{
return m_Enumerable.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return ((IEnumerable) m_Enumerable).GetEnumerator();
}
}
public class CompositeDisposableEnumerable<T> : IDisposableEnumerable<T>
{
private readonly IDisposableEnumerable<T>[] m_DisposableEnumerables;
public CompositeDisposableEnumerable(params IDisposableEnumerable<T>[] disposable_enumerables)
{
m_DisposableEnumerables = disposable_enumerables;
}
public IEnumerator<T> GetEnumerator()
{
foreach (var disposable_enumerable in m_DisposableEnumerables)
{
foreach (var item in disposable_enumerable)
yield return item;
}
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
public void Dispose()
{
foreach (var disposable_enumerable in m_DisposableEnumerables)
disposable_enumerable.Dispose();
}
}
UPDATE:
Here is a sample usage:
public IDisposableEnumerable<T> GetItems<T>()
{
List<T> collection1 = ....;
DeferredResultCollection<T> collection2 = new DeferredResultCollection<T> (async_cursor);
return new CompositeDisposableEnumerable<T>(new EnumerableWrapper<T>(collection1), collection2);
}
And from the consumer side:
using(var items = GetItems<string>())
{
//do something with items
} //This will invoke `Dispose` which will be propagated finally to DeferredResultCollection.Dispose and thus to IAsyncCursor.Dispose

Related

Why implementation of IEnumerable not require when iterate using foreach

I was looking into the IEnumerable and trying the example given in this link. I understand that when we iterate using foreach the GetEnumerator() method gets call because my List class has implemented IEnumerable (or may be I am wrong).
public class List<T> : IEnumerable
{
private T[] _collection;
public List(T[] inputs)
{
_collection = new T[inputs.Length];
for (int i = 0; i < inputs.Length; i++)
{
_collection[i] = inputs[i];
}
}
IEnumerator IEnumerable.GetEnumerator()
{
return (IEnumerator)GetEnumerator();
}
public CollectionEnum<T> GetEnumerator()
{
return new CollectionEnum<T>(_collection);
}
}
public class CollectionEnum<T> : IEnumerator
{
public T[] _collection ;
int position = -1;
public CollectionEnum(T[] list)
{
_collection = list;
}
public bool MoveNext()
{
position++;
return (position < _collection.Length);
}
//implementation on Current and Reset
}
Then, it is also mentioned that implementation of IEnumerable is not required to iterate using foreach. So, in the above code if I remove the implementation of IEnumerable the foreach must work. So my List<> class looks like
public class List<T>
{
private T[] _collection;
public List(T[] persons)
{
_collection = new T[persons.Length];
for (int i = 0; i < persons.Length; i++)
{
_collection[i] = persons[i];
}
}
public CollectionEnum<T> GetEnumerator()
{
return new CollectionEnum<T>(_collection);
}
}
And which does work. Now I did not understand how foreach knows my class has a method call GetEnumerator() which returns a IEnumerator type.
The article you linked to provided the explanation to you already in the remarks.
If your collection does not implement IEnumerable, you must still
follow the iterator pattern to support this syntax by providing a
GetEnumerator method that returns an interface, class or struct....that contains a Current property, and MoveNext and Reset methods as
described by IEnumerator, but the class does not have to implement
IEnumerator.
As Nkosi mentions, in interpreting foreach, the compiler looks for a pattern originally represented in IEnumerable and IEnumerator.
Earlier versions of the C# compiler required the implementation of these interfaces. However, with the advent of LINQ, the language and compiler have been adjusted to do more of recognizing patterns.
For instance, you can create a LINQ query around an object that has a Where method but doesn't implement IEnumerable.
Similarly, you can await any object that follows the Awaitable Pattern not just Task or Task.
Once you understand the particular methods the compiler is looking for to satisfy a pattern it becomes easier to wrap your head around why IEnumerable is not required for foreach. Remember also that foreach is really just syntactic sugar for traversing a collection of objects.

Generic lists: The type arguments for method cannot be inferred from the usage in lambdas

I got a problem in C#, giving me an error 'The type arguments for method cannot be inferred from the usage'. Seems that the compiler cannot determine the correct interface, if I derive a generic list from a non-generic one:
Code:
public class SpecialItem : BaseItem
{
public string Title { get; set; }
}
public class BaseItem
{
public string Name { get; set; }
}
public class GenericList<T> : NongenericBaseList, IEnumerable<T>
where T: BaseItem
{
public new T this[int index]
{
get { return _items[index] as T; }
}
public new IEnumerator<T> GetEnumerator()
{
var iter = _items.GetEnumerator();
while (iter.MoveNext())
{
yield return iter.Current as T;
}
}
}
public class NongenericBaseList : IEnumerable<BaseItem>
{
protected List<BaseItem> _items;
public BaseItem this[int index]
{
get { return _items[index]; }
}
public IEnumerator<BaseItem> GetEnumerator()
{
return _items.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
Usage:
var genericList = new GenericList<SpecialItem>();
foreach (var item in genericList) // Uses IEnmerable<SpecialItem>, OK!
{
Console.WriteLine(item.Title);
}
var l = genericList.ToList(); // ERROR!
The ForEarch gets the correct Enumerator (SpecialItem), but the lambda does not know what to use (IEnumerable<BaseItem> or IEnumerable<SpecialItem>).
What to do? How can I set IEnumerable<SpecialItem> as 'default' interface? I dont want to explicetly code the type all the time like this:
var l = genericList.ToList<SpecialItem>();
First of all: kudos for providing a self-contained example!
You cannot specify a 'default' interface for type inference. The argument type for ToList<T> cannot be resolved because it is ambiguous, the type implements both IEnumerable<BaseItem> and IEnumerable<SpecialItem>, and both versions are applicable.
Is there a possibility to remove the class NongenericBaseList completely, and use the GenericList<T>instead? That would solve your problem; you can use GenericList<BaseItem> instead of NongenericBaseList
Another option is to reverse the inheritance; make NongenericBaseList empty and deriving from GenericList<BaseItem>.
Thanks to Sriram Sakthivel, he guided me to a solution with a very small overhead. To make things clear I wanted to make sure that:
Both lists, the generic and nongeneric one must be the same object. Therefore I have to derive, not packing in a wrapper.
Both lists must support access via loops (ForEach) and lambdas / extension methods without the need to explicitly typing the class name.
They have to implement IList<T>, so T out is not an option.
In short, the following code must compile without errors:
// Generic
var genericList = new GenericList<SpecialItem>();
foreach (var item in genericList)
{
Console.WriteLine(item.Title);
}
var l = genericList.ToList();
// Nongeneric
var nongenericList = genericList as NongenericBaseList;
foreach (var item in nongenericList)
{
Console.WriteLine(item.Name);
}
var nl = nongenericList.ToList();
I came to the conclusion, that this is not possible with the upper code (correct me if that is not true!). The loops are working fine, but either the generic or the nongeneric list does not work with .ToList() or other extension methods, because the compiler cannot inferre the type.
Now I used Sriram Sakthivel tipp, implementing only IEnumerable without <T>. But that allone would make it impossible to use extension methods at all even if you explicitely write the type.
I simply added a property, casting the collection:
public class NongenericBaseList : IEnumerable // Without the T!
{
protected List<BaseItem> _items;
// The property
public IEnumerable<BaseItem> L
{
get { return this as IEnumerable<BaseItem>; }
}
public BaseItem this[int index]
{
get { return _items[index]; }
}
public IEnumerator<BaseItem> GetEnumerator()
{
return _items.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
Now I can type:
var nl = nongenericList.L.ToList();
Any better solution would be appreciated!

Complexity between IEnumerable<T> return type implementation

Is there a significant complexity difference between these two implementation or does the compiler optimize it anyway?
Usage:
for(int i = 0; i < int.MaxValue; i++)
{
foreach(var item in GoodItems)
{
if(DoSomethingBad(item))
break; // this is later added.
}
}
Implementation (1):
public IEnumerable<T> GoodItems
{
get { return _list.Where(x => x.IsGood); }
}
Implementation (2):
public IEnumerable<T> GoodItems
{
get { foreach(var item in _list.Where(x => x.IsGood)) yield return item; }
}
It appears that IEnumerable methods should always be implemented using (2)? When is one better than the other?
I just built an example program and then used ILSpy to examine the output assembly. The second option will actually generate an extra class that wraps the call to Where but adds zero value to the code. The extra layer the code must follow will probably not cause performance issues in most programs but consider all the extra syntax just to perform the same thing at a slightly slower speed. Not worth it in my book.
where uses yield return internally. You don't need to wrap it in another yield return.
You do _list.where(x => x.IsGood); in both. With that said, isn't it obvious which has to be the better usage?
yield return has its usages, but this scenario, especially in a getter, is not the one
The extra code without payload in "implementation 2" is the less evil here.
Both variants lead to undesirable creation of new object each time you call the property getter. So, results of two sequential getter calls will not be equal:
interface IItem
{
bool IsGood { get; set; }
}
class ItemsContainer<T>
where T : IItem
{
private readonly List<T> items = new List<T>();
public IEnumerable<T> GoodItems
{
get { return items.Where(item => item.IsGood); }
}
// ...
}
// somewhere in code
class Item : IItem { /* ... */ }
var container = new ItemsContainer<Item>();
Console.WriteLine(container.GoodItems == container.GoodItems); // False; Oops!
You should avoid this side-effect:
class ItemsContainer<T>
where T : IItem
{
private readonly List<T> items;
private readonly Lazy<IEnumerable<T>> goodItems;
public ItemsContainer()
{
this.items = new List<T>();
this.goodItems = new Lazy<IEnumerable<T>>(() => items.Where(item => item.IsGood));
}
public IEnumerable<T> GoodItems
{
get { return goodItems.Value; }
}
// ...
}
or make a method instead of property:
public IEnumerable<T> GetGoodItems()
{
return _list.Where(x => x.IsGood);
}
Also, the property is not a good idea, if you want to provide snapshot of your items to the client code.
Internally, the first version gets compiled down to something that looks like this:
public IEnumerable<T> GoodItems
{
get
{
foreach (var item in _list)
if (item.IsGood)
yield return item;
}
}
Whereas the second one will now look something like:
public IEnumerable<T> GoodItems
{
get
{
foreach (var item in GoodItemsHelper)
yield return item;
}
}
private IEnumerable<T> GoodItemsHelper
{
get
{
foreach (var item in _list)
if (item.IsGood)
yield return item;
}
}
The Where clause in LINQ is implemented with deferred execution. So there's no need to apply the foreach (...) yield return ... pattern. You're making more work for yourself, and potentially for the runtime.
I don't know if the second version gets jitted to the same thing as the first. Semantically, the two are distinct in that the first does a single round of deferred execution while the second does two rounds. On those grounds I'd argue that the second would be more complex.
The real question you need to ask is: When you're exposing the IEnumerable, what guarantees are you making? Are you saying that you want to simply provide forward iteration? Or are you stating that your interface provides deferred execution?
In the code below, my intent for is to simply provide forward enumeration without random access:
private List<Int32> _Foo = new List<Int32>() { 1, 2, 3, 4, 5 };
public IEnumerable<Int32> Foo
{
get
{
return _Foo;
}
}
But here, I want to prevent unnecessary computation. I want my expensive computation to be performed only when a result is requested.
private List<Int32> _Foo = new List<Int32>() { 1, 2, 3, 4, 5 };
public IEnumerable<Int32> Foo
{
get
{
foreach (var item in _Foo)
{
var result = DoSomethingExpensive(item);
yield return result;
}
}
}
Even though both versions of Foo look identical on the outside, their internal implementation does different things. That's the part that you need to watch out for. When you use LINQ, you don't need to worry about deferring execution since most operators do it for you. In your own code, you may wish to go with the first or second depending on your needs.

IEnumerable from IEnumerator

I have writen about custom IEnumerator. Whats the simplest way to make IEnumerable from it ? Ideal solution (one line of code) would be if there was some class for that purpose. Or do I have to create my own ?
There's no built-in method, unfortunately. I have this extension method that I use often enough:
static IEnumerable Iterate(this IEnumerator iterator)
{
while (iterator.MoveNext())
yield return iterator.Current;
}
In my collection of C# utils I have this:
class Enumerable<T> : IEnumerable<T>
{
Func<IEnumerator<T>> factory;
public Enumerable(Func<IEnumerator<T>> factory) { this.factory = factory; }
public IEnumerator<T> GetEnumerator() { return this.factory(); }
IEnumerator IEnumerable.GetEnumerator() { return this.GetEnumerator(); }
}
This takes an IEnumerator factory function, which usually can be provided very easily instead of the single IEnumerator instance (which yields wrong results after first iteration and breaks the semantics of IEnumerable). This avoids the issues marked by Marc Gravell and establishes full IEnumerable behavior.
I use it this way:
IEnumerable<Fruit> GetFruits()
{
var arg1 = ...
return new Enumerable<Fruit>(() => new FruitIterator(arg1, arg2, ...));
}
I would really approach this the other way around; while you can (as per Mike P's excellent answer) wrap an enumerator to pretend to be enumerable, there are some things that you can't really do - for example, it is hoped (although, to be fair, not insisted) that you can obtain multiple enumerators from an enumerable, ideally isolated and repeatable. So if I do:
Assert.AreEqual(sequence.Sum(), sequence.Sum());
but if you "spoof" the enumerator into an enumerable, the second sequence will be empty. Or if you do them in parallel - just bizarre. And there are methods that process them in parallel - consider:
Assert.IsTrue(sequence.SequenceEqual(sequence));
this works both enumerators forward at the same time, so if you only have one enumerator, you are fairly scuppered.
There is a reset on enumerators, but this is largely a design mistake and shouldn't be used (it is even a formal requirement in the spec that iterator blocks throw an exception if you call it).
A better (IMO) question is "how do I get an enumerator from an enumerable", in which case the answer is "call GetEnumerator(), and remember to check to dispose to iterator" - or in simpler terms "use foreach".
Pretty simple:
class Enumerate : IEnumerable
{
private Enumerate IEnumerator it;
public Enumerate(IEnumerator it) { this.it = it; }
public IEnumerator GetEnumerator() { return this.it; }
}
This also allows the user to call IEnumerator.Reset() if the enumerator you gave it supports it.
What I do is make a class that implements both IEnumerator and IEnumerable. Make GetEnumerator() return itself and you can iterate it like normal.
public class MyClassEnumerator : IEnumerator<MyClass>, IEnumerable<MyClass>
{
public MyClass Current { get; private set; }
object IEnumerator.Current => Current;
public void Reset()
{
...
}
public bool MoveNext()
{
...
}
public IEnumerator<MyClass> GetEnumerator()
{
return this;
}
IEnumerator IEnumerable.GetEnumerator()
{
return this;
}
public void Dispose()
{
...
}
}

Passing a single item as IEnumerable<T>

Is there a common way to pass a single item of type T to a method which expects an IEnumerable<T> parameter? Language is C#, framework version 2.0.
Currently I am using a helper method (it's .Net 2.0, so I have a whole bunch of casting/projecting helper methods similar to LINQ), but this just seems silly:
public static class IEnumerableExt
{
// usage: IEnumerableExt.FromSingleItem(someObject);
public static IEnumerable<T> FromSingleItem<T>(T item)
{
yield return item;
}
}
Other way would of course be to create and populate a List<T> or an Array and pass it instead of IEnumerable<T>.
[Edit] As an extension method it might be named:
public static class IEnumerableExt
{
// usage: someObject.SingleItemAsEnumerable();
public static IEnumerable<T> SingleItemAsEnumerable<T>(this T item)
{
yield return item;
}
}
Am I missing something here?
[Edit2] We found someObject.Yield() (as #Peter suggested in the comments below) to be the best name for this extension method, mainly for brevity, so here it is along with the XML comment if anyone wants to grab it:
public static class IEnumerableExt
{
/// <summary>
/// Wraps this object instance into an IEnumerable<T>
/// consisting of a single item.
/// </summary>
/// <typeparam name="T"> Type of the object. </typeparam>
/// <param name="item"> The instance that will be wrapped. </param>
/// <returns> An IEnumerable<T> consisting of a single item. </returns>
public static IEnumerable<T> Yield<T>(this T item)
{
yield return item;
}
}
Well, if the method expects an IEnumerable you've got to pass something that is a list, even if it contains one element only.
passing
new[] { item }
as the argument should be enough I think
In C# 3.0 you can utilize the System.Linq.Enumerable class:
// using System.Linq
Enumerable.Repeat(item, 1);
This will create a new IEnumerable that only contains your item.
Your helper method is the cleanest way to do it, IMO. If you pass in a list or an array, then an unscrupulous piece of code could cast it and change the contents, leading to odd behaviour in some situations. You could use a read-only collection, but that's likely to involve even more wrapping. I think your solution is as neat as it gets.
In C# 3 (I know you said 2), you can write a generic extension method which might make the syntax a little more acceptable:
static class IEnumerableExtensions
{
public static IEnumerable<T> ToEnumerable<T>(this T item)
{
yield return item;
}
}
client code is then item.ToEnumerable().
This helper method works for item or many.
public static IEnumerable<T> ToEnumerable<T>(params T[] items)
{
return items;
}
I'm kind of surprised that no one suggested a new overload of the method with an argument of type T to simplify the client API.
public void DoSomething<T>(IEnumerable<T> list)
{
// Do Something
}
public void DoSomething<T>(T item)
{
DoSomething(new T[] { item });
}
Now your client code can just do this:
MyItem item = new MyItem();
Obj.DoSomething(item);
or with a list:
List<MyItem> itemList = new List<MyItem>();
Obj.DoSomething(itemList);
Either (as has previously been said)
MyMethodThatExpectsAnIEnumerable(new[] { myObject });
or
MyMethodThatExpectsAnIEnumerable(Enumerable.Repeat(myObject, 1));
As a side note, the last version can also be nice if you want an empty list of an anonymous object, e.g.
var x = MyMethodThatExpectsAnIEnumerable(Enumerable.Repeat(new { a = 0, b = "x" }, 0));
I agree with #EarthEngine's comments to the original post, which is that 'AsSingleton' is a better name. See this wikipedia entry. Then it follows from the definition of singleton that if a null value is passed as an argument that 'AsSingleton' should return an IEnumerable with a single null value instead of an empty IEnumerable which would settle the if (item == null) yield break; debate. I think the best solution is to have two methods: 'AsSingleton' and 'AsSingletonOrEmpty'; where, in the event that a null is passed as an argument, 'AsSingleton' will return a single null value and 'AsSingletonOrEmpty' will return an empty IEnumerable. Like this:
public static IEnumerable<T> AsSingletonOrEmpty<T>(this T source)
{
if (source == null)
{
yield break;
}
else
{
yield return source;
}
}
public static IEnumerable<T> AsSingleton<T>(this T source)
{
yield return source;
}
Then, these would, more or less, be analogous to the 'First' and 'FirstOrDefault' extension methods on IEnumerable which just feels right.
This is 30% faster than yield or Enumerable.Repeat when used in foreach due to this C# compiler optimization, and of the same performance in other cases.
public struct SingleSequence<T> : IEnumerable<T> {
public struct SingleEnumerator : IEnumerator<T> {
private readonly SingleSequence<T> _parent;
private bool _couldMove;
public SingleEnumerator(ref SingleSequence<T> parent) {
_parent = parent;
_couldMove = true;
}
public T Current => _parent._value;
object IEnumerator.Current => Current;
public void Dispose() { }
public bool MoveNext() {
if (!_couldMove) return false;
_couldMove = false;
return true;
}
public void Reset() {
_couldMove = true;
}
}
private readonly T _value;
public SingleSequence(T value) {
_value = value;
}
public IEnumerator<T> GetEnumerator() {
return new SingleEnumerator(ref this);
}
IEnumerator IEnumerable.GetEnumerator() {
return new SingleEnumerator(ref this);
}
}
in this test:
// Fastest among seqs, but still 30x times slower than direct sum
// 49 mops vs 37 mops for yield, or c.30% faster
[Test]
public void SingleSequenceStructForEach() {
var sw = new Stopwatch();
sw.Start();
long sum = 0;
for (var i = 0; i < 100000000; i++) {
foreach (var single in new SingleSequence<int>(i)) {
sum += single;
}
}
sw.Stop();
Console.WriteLine($"Elapsed {sw.ElapsedMilliseconds}");
Console.WriteLine($"Mops {100000.0 / sw.ElapsedMilliseconds * 1.0}");
}
As I have just found, and seen that user LukeH suggested too, a nice simple way of doing this is as follows:
public static void PerformAction(params YourType[] items)
{
// Forward call to IEnumerable overload
PerformAction(items.AsEnumerable());
}
public static void PerformAction(IEnumerable<YourType> items)
{
foreach (YourType item in items)
{
// Do stuff
}
}
This pattern will allow you to call the same functionality in a multitude of ways: a single item; multiple items (comma-separated); an array; a list; an enumeration, etc.
I'm not 100% sure on the efficiency of using the AsEnumerable method though, but it does work a treat.
Update: The AsEnumerable function looks pretty efficient! (reference)
Although it's overkill for one method, I believe some people may find the Interactive Extensions useful.
The Interactive Extensions (Ix) from Microsoft includes the following method.
public static IEnumerable<TResult> Return<TResult>(TResult value)
{
yield return value;
}
Which can be utilized like so:
var result = EnumerableEx.Return(0);
Ix adds new functionality not found in the original Linq extension methods, and is a direct result of creating the Reactive Extensions (Rx).
Think, Linq Extension Methods + Ix = Rx for IEnumerable.
You can find both Rx and Ix on CodePlex.
I recently asked the same thing on another post
Is there a way to call a C# method requiring an IEnumerable<T> with a single value? ...with benchmarking.
I wanted people stopping by here to see the brief benchmark comparison shown at that newer post for 4 of the approaches presented in these answers.
It seems that simply writing new[] { x } in the arguments to the method is the shortest and fastest solution.
This may not be any better but it's kind of cool:
Enumerable.Range(0, 1).Select(i => item);
Sometimes I do this, when I'm feeling impish:
"_".Select(_ => 3.14) // or whatever; any type is fine
This is the same thing with less shift key presses, heh:
from _ in "_" select 3.14
For a utility function I find this to be the least verbose, or at least more self-documenting than an array, although it'll let multiple values slide; as a plus it can be defined as a local function:
static IEnumerable<T> Enumerate (params T[] v) => v;
// usage:
IEnumerable<double> example = Enumerate(1.234);
Here are all of the other ways I was able to think of (runnable here):
using System;
using System.Collections.Generic;
using System.Linq;
public class Program {
public static IEnumerable<T> ToEnumerable1 <T> (T v) {
yield return v;
}
public static T[] ToEnumerable2 <T> (params T[] vs) => vs;
public static void Main () {
static IEnumerable<T> ToEnumerable3 <T> (params T[] v) => v;
p( new string[] { "three" } );
p( new List<string> { "three" } );
p( ToEnumerable1("three") ); // our utility function (yield return)
p( ToEnumerable2("three") ); // our utility function (params)
p( ToEnumerable3("three") ); // our local utility function (params)
p( Enumerable.Empty<string>().Append("three") );
p( Enumerable.Empty<string>().DefaultIfEmpty("three") );
p( Enumerable.Empty<string>().Prepend("three") );
p( Enumerable.Range(3, 1) ); // only for int
p( Enumerable.Range(0, 1).Select(_ => "three") );
p( Enumerable.Repeat("three", 1) );
p( "_".Select(_ => "three") ); // doesn't have to be "_"; just any one character
p( "_".Select(_ => 3.3333) );
p( from _ in "_" select 3.0f );
p( "a" ); // only for char
// these weren't available for me to test (might not even be valid):
// new Microsoft.Extensions.Primitives.StringValues("three")
}
static void p <T> (IEnumerable<T> e) =>
Console.WriteLine(string.Join(' ', e.Select((v, k) => $"[{k}]={v,-8}:{v.GetType()}").DefaultIfEmpty("<empty>")));
}
For those wondering about performance, while #mattica has provided some benchmarking information in a similar question referenced above, My benchmark tests, however, have provided a different result.
In .NET 7, yield return value is ~9% faster than new T[] { value } and allocates 75% the amount of memory. In most cases, this is already hyper-performant and is as good as you'll ever need.
I was curious if a custom single collection implementation would be faster or more lightweight. It turns out because yield return is implemented as IEnumerator<T> and IEnumerable<T>, the only way to beat it in terms of allocation is to do that in my implementation as well.
If you're passing IEnumerable<> to an outside library, I would strongly recommend not doing this unless you're very familiar with what you're building. That being said, I made a very simple (not-reuse-safe) implementation which was able to beat the yield method by 5ns and allocated only half as much as the array.
Because all tests were passed an IEnumerable<T>, value types generally performed worse than reference types. The best implementation I had was actually the simplest - you can look at the SingleCollection class in the gist I linked to. (This was 2ns faster than yield return, but allocated 88% of what the array would, compared to the 75% allocated for yield return.)
TL:DR; if you care about speed, use yield return item. If you really care about speed, use a SingleCollection.
The easiest way I'd say would be new T[]{item};; there's no syntax to do this. The closest equivalent that I can think of is the params keyword, but of course that requires you to have access to the method definition and is only usable with arrays.
Enumerable.Range(1,1).Select(_ => {
//Do some stuff... side effects...
return item;
});
The above code is useful when using like
var existingOrNewObject = MyData.Where(myCondition)
.Concat(Enumerable.Range(1,1).Select(_ => {
//Create my object...
return item;
})).Take(1).First();
In the above code snippet there is no empty/null check, and it is guaranteed to have only one object returned without afraid of exceptions. Furthermore, because it is lazy, the closure will not be executed until it is proved there is no existing data fits the criteria.
To be filed under "Not necessarily a good solution, but still...a solution" or "Stupid LINQ tricks", you could combine Enumerable.Empty<>() with Enumerable.Append<>()...
IEnumerable<string> singleElementEnumerable = Enumerable.Empty<string>().Append("Hello, World!");
...or Enumerable.Prepend<>()...
IEnumerable<string> singleElementEnumerable = Enumerable.Empty<string>().Prepend("Hello, World!");
The latter two methods are available since .NET Framework 4.7.1 and .NET Core 1.0.
This is a workable solution if one were really intent on using existing methods instead of writing their own, though I'm undecided if this is more or less clear than the Enumerable.Repeat<>() solution. This is definitely longer code (partly due to type parameter inference not being possible for Empty<>()) and creates twice as many enumerator objects, however.
Rounding out this "Did you know these methods exist?" answer, Array.Empty<>() could be substituted for Enumerable.Empty<>(), but it's hard to argue that makes the situation...better.
I'm a bit late to the party but I'll share my way anyway.
My problem was that I wanted to bind the ItemSource or a WPF TreeView to a single object. The hierarchy looks like this:
Project > Plot(s) > Room(s)
There was always going to be only one Project but I still wanted to Show the project in the Tree, without having to pass a Collection with only that one object in it like some suggested.
Since you can only pass IEnumerable objects as ItemSource I decided to make my class IEnumerable:
public class ProjectClass : IEnumerable<ProjectClass>
{
private readonly SingleItemEnumerator<AufmassProjekt> enumerator;
...
public IEnumerator<ProjectClass > GetEnumerator() => this.enumerator;
IEnumerator IEnumerable.GetEnumerator() => this.GetEnumerator();
}
And create my own Enumerator accordingly:
public class SingleItemEnumerator : IEnumerator
{
private bool hasMovedOnce;
public SingleItemEnumerator(object current)
{
this.Current = current;
}
public bool MoveNext()
{
if (this.hasMovedOnce) return false;
this.hasMovedOnce = true;
return true;
}
public void Reset()
{ }
public object Current { get; }
}
public class SingleItemEnumerator<T> : IEnumerator<T>
{
private bool hasMovedOnce;
public SingleItemEnumerator(T current)
{
this.Current = current;
}
public void Dispose() => (this.Current as IDisposable).Dispose();
public bool MoveNext()
{
if (this.hasMovedOnce) return false;
this.hasMovedOnce = true;
return true;
}
public void Reset()
{ }
public T Current { get; }
object IEnumerator.Current => this.Current;
}
This is probably not the "cleanest" solution but it worked for me.
EDIT
To uphold the single responsibility principle as #Groo pointed out I created a new wrapper class:
public class SingleItemWrapper : IEnumerable
{
private readonly SingleItemEnumerator enumerator;
public SingleItemWrapper(object item)
{
this.enumerator = new SingleItemEnumerator(item);
}
public object Item => this.enumerator.Current;
public IEnumerator GetEnumerator() => this.enumerator;
}
public class SingleItemWrapper<T> : IEnumerable<T>
{
private readonly SingleItemEnumerator<T> enumerator;
public SingleItemWrapper(T item)
{
this.enumerator = new SingleItemEnumerator<T>(item);
}
public T Item => this.enumerator.Current;
public IEnumerator<T> GetEnumerator() => this.enumerator;
IEnumerator IEnumerable.GetEnumerator() => this.GetEnumerator();
}
Which I used like this
TreeView.ItemSource = new SingleItemWrapper(itemToWrap);
EDIT 2
I corrected a mistake with the MoveNext() method.
I prefer
public static IEnumerable<T> Collect<T>(this T item, params T[] otherItems)
{
yield return item;
foreach (var otherItem in otherItems)
{
yield return otherItem;
}
}
This lets you call item.Collect() if you want the singleton, but it also lets you call item.Collect(item2, item3) if you want

Categories

Resources