Passing a single item as IEnumerable<T>

Viewed 117497

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&lt;T&gt;
    /// 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&lt;T&gt; consisting of a single item. </returns>
    public static IEnumerable<T> Yield<T>(this T item)
    {
        yield return item;
    }
}
19 Answers

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.

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.

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>")));

}
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

Related