The implementation of Enumerable.AsEnumerable<T>(this IEnumerable<T> source) simply returns source. However Observable.AsObservable<T>(this IObservable<T> source) returns an AnonymousObservable<T> subscribing to the source rather than simply returning the source.
I understand these methods are really useful for changing the monad within a single query (going from IQueryable => IEnumerable). So why do the implementations differ?
The Observable version is more defensive, in that you can’t cast it to some known type (if it original were implemented as a Subject<T> you’d never be able to cast it as such). So why does the Enumerable version not do something similar? If my underlying type is a List<T> but expose it as IEnumerable<T> through AsEnumerable, it will be possible to cast back to a List<T>.
Please note that this isn’t a question on how to expose IEnumerable<T> without being able to cast to the underlying, but why the implementations between Enumerable and Observable are semantically different.
Your question is answered by the documentation, which I encourage you to read when you have such questions.
The purpose of AsEnumerable is to hint to the compiler “please stop using IQueryable and start treating this as an in-memory collection”.
As the documentation states:
If you want to hide the implementation of an underlying sequence, use
sequence.Select(x=>x)orToListorToArrayif you don’t care that you’re making a mutable sequence.The purpose of AsObservable is to hide the implementation of the underlying collection. As the documentation says:
Since the two methods have completely different purposes, they have completely different implementations.