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\$

locked by Jamal May 24 '15 at 3:00

This question exists because it has historical significance, but it is not considered a good, on-topic question for this site so please do not use it as evidence that you can ask similar questions here. This question and its answers are frozen and cannot be changed. See the help center for guidance on writing a good question.

Read more about locked posts here.

  • \$\begingroup\$ Doesn't the first method return an array of T while the second one returns an IEnumerable of T? \$\endgroup\$ – jb. Feb 20 '11 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\$ – Peter Taylor Feb 23 '11 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 '11 at 19:24
  • \$\begingroup\$ @supercat @Peter, Very good name! I will use it. \$\endgroup\$ – Amir Rezaei Feb 25 '11 at 7:04
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
    \$\begingroup\$ you don't need the parens around (other) in either case. \$\endgroup\$ – Maslow Mar 31 '11 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\$
  • \$\begingroup\$ That is why in the Reactive Extensions the EnumerableEx class has a Return method, that does exactly that. \$\endgroup\$ – Iñaki Elcoro Feb 20 '11 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.