4
votes
\$\begingroup\$

I have an extension method that does this:

public static IEnumerable<T> ToIEnumerable<T>(this T source) where T : new()
{
    return new[] { source };
}

I need to be able to convert any object to an IEnumerable.

For example when I use the .NET Except method:

public static IEnumerable<TSource> Except<TSource>(this IEnumerable<TSource> first)

I can call Except by doing the following:

return objects.Except(this.ToIEnumerable());

Is ToIEnumerable<T> good practice or should I solve the problem in differently?

\$\endgroup\$
4
  • \$\begingroup\$ Doesn't the first method return an array of T while the second one returns an IEnumerable of T? \$\endgroup\$
    – jb.
    Feb 20, 2011 at 9:19
  • 2
    \$\begingroup\$ There are probably better names for the method. AsSingleton is what I'd use unless it risks being confused for the singleton design pattern. \$\endgroup\$ Feb 23, 2011 at 10:32
  • \$\begingroup\$ I agree with Peter. I would expect that calling ToEnumerable on a collection would yield the contents of the collection (maybe taking a snapshot), rather than an enumerable containing the collection as a single item. Returning an array is probably more efficient than using a Yield, though it has the slight disadvantage that if it's cast back to an array one could write to it. Not a huge problem (since ToIEnumerable creates a new array, such a write would only affect future attempts to enumerate it) but worth noting. \$\endgroup\$
    – supercat
    Feb 24, 2011 at 19:24
  • \$\begingroup\$ @supercat @Peter, Very good name! I will use it. \$\endgroup\$ Feb 25, 2011 at 7:04

3 Answers 3

7
votes
\$\begingroup\$

While I don't see why ToIEnumerable is bad practice, in this specific case I think it is. You're comparing with only one object; why not just attach a where clause on to things? I.e.

return objects.Where((other) => other != this);

or possibly

return objects.Where((other) => !Object.ReferenceEquals(other, this));

Not only will this perform better than Except here, but it's easier to understand, and avoids the entire ToIEnumerable thing entirely.

\$\endgroup\$
1
  • 1
    \$\begingroup\$ you don't need the parens around (other) in either case. \$\endgroup\$
    – Maslow
    Mar 31, 2011 at 0:36
3
votes
\$\begingroup\$

I don't see why not.

If you wanted to be 'monadically pure', you could call it Return (because in monads, the function which performs 'a -> M 'a is called return).

(See this question: FromSingleItem, or AsEnumerable - someone there also suggested using the existing Enumerable.Repeat(T item, int count))

\$\endgroup\$
1
  • \$\begingroup\$ That is why in the Reactive Extensions the EnumerableEx class has a Return method, that does exactly that. \$\endgroup\$ Feb 20, 2011 at 21:39
1
vote
\$\begingroup\$

It's potentially annoying to have an extension method like that turn up on almost every type. With just a single one, it's probably a minor irritation at most, but in the future you may find yourself coming up with more this object or this T extension methods, and either you'll start to get a very clogged up Intellisense. So think about whether this is really something that you want frequently enough to justify it. If you're working on code that may be maintained by colleagues, check their opinions.

Note also that new[] { source } actually has fewer characters than source.ToIEnumerable(). Which is more readable and clear in stating what it is doing is arguable, but at least the array is instantly universally recognisable.

So while it would be harsh to say that it's "bad practice", on balance I would probably advise slightly against it. If the benefits seem to outweigh the costs to you, though, then go for it.

As a side-note, you don't need your where T : new() condition, either. It's the array that you're creating a new instance of, not the T itself.

\$\endgroup\$

Not the answer you're looking for? Browse other questions tagged or ask your own question.