An extension method that works on IEnumerable <T> and IQueryable <T>?

I need an extension method that works with both my list and IQueryable. The extension methods are given below, but if I add another identical extension method, but on a completely different type, I get an ambiguous call to compile the errors. Why is this? Isn't the compiler smart enough to find out which extension method works? I mean, only one of these calls is valid, why can't the compiler say? Many thanks!

class ClassA { public bool IsActive{ get; set;} } class ClassB { public bool IsActive { get; set;} } // then here are my extensions public static T IsActive<T>(this T enumerableOrQueryable, bool isActive) where T : IEnumerable<ClassA> { return (T)enumerableOrQueryable.Where(x => x.IsActive == isActive); } public static T IsActive<T>(this T enumerableOrQueryable, bool isActive) where T : IEnumerable<ClassB> { return (T)enumerableOrQueryable.Where(x => x.IsActive == isActive); } 
+6
source share
3 answers

Overload rules do not take into account the restrictions on the methods that he considers - he determines which overload is best, and then checks whether the restrictions are consistent.

The compiler strictly follows the rules of the C # specification.

Related Blog Entries:

EDIT: Note that using "enumerableOrQueryable" will always convert your lambda expression to a delegate, not an expression tree. Therefore, if you want it to execute logic differently for the database, you still need a change.

EDIT: Your idea won't work either, because you still won't get the same type of result - if you call Where on a List<string> , the return value is not List<string> .

What you can do is if you can introduce a new interface that will be implemented by both ClassA and ClassB:

 public static IQueryable<T> IsActive<T>(this IQueryable<T> source, bool isActive) where T : ICanBeActive { // Lambda converted to an expression tree return source.Where(x => x.IsActive == isActive); } public static IEnumerable<T> IsActive<T>(this IEnumerable<T> source, bool isActive) where T : ICanBeActive { // Lambda converted to a delegate return source.Where(x => x.IsActive == isActive); } 
+8
source

The compiler cannot disambiguate the general constraints. In your case, can't you just do something like that?

 public static IEnumerable<ClassA> IsActive(this IEnumerable<ClassA> enumerableOrQueryable, bool isActive) { return enumerableOrQueryable.Where(x => x.IsActive == isActive); } 
+1
source

You can try something like this:

 public interface IActivatable { bool IsActive { get; set; } } public class ClassA : IActivatable { public bool IsActive{ get; set;} } public class ClassB : IActivatable { public bool IsActive { get; set;} } public static class Ext { public static IEnumerable<T> IsActive<T>(this IEnumerable<T> collection, bool isActive) where T : IActivatable { return collection.Where(x => x.IsActive == isActive); } } 
0
source

Source: https://habr.com/ru/post/898972/


All Articles