Reputation: 31055
Is there a recommended built-in type in C# that collections can be converted/cast to that will still allow deferred execution, but not allow the type to be cast back into IQueryable? (Like IEnumerable<T>
can in some cases)
Upvotes: 0
Views: 191
Reputation: 205749
The "built in" way to guard IQueryable<T>
would be Enumerable.Select
like this
IQueryable<T> source = ...;
var result = source.AsEnumerable().Select(x => x);
AsEnumerable
is not enough because it is a simply cast. But it's needed to ensure Enumerable.Select
is used instead of Queryable.Select
.
However, other than being "built in", I see no benefit of this approach and prefer the custom extension method like in another answer, although this can be used as implementation instead of iterator function (which also has no benefit, but rather a drawback due to unnecessary delegate call, so really the custom iterator function is the right way to go).
Upvotes: 4
Reputation: 3603
A built in type no but it's pretty easy to do :
public static class Utils
{
public static IEnumerable<T> AsDefferedEnumerable<T>(this IQueryable<T> Source)
{
foreach (var item in Source)
{
yield return item;
}
}
}
This way you're not returning a casted IQueryable (that could be casted back) but creating a new IEnumerable wrapping it , you don't even need a new type at all for that you just end up with an IEnumerable that will itself enumerate the IQueryable as it is enumerated without exposing it.
Edit : sample of a wrapper object (untested)
public class HideImplementationEnumerable<T>
{
public HideImplementationEnumerable(IEnumerable<T> Source)
{
this.Source = Source;
}
private IEnumerable<T> Source;
public IEnumerable<T> Value
{
get
{
foreach (var item in Source)
{
yield return item;
}
}
}
}
Upvotes: 3