Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Extension method that works on IEnumerable<T> and IQueryable<T>?

I want an extension method that works on both my List and IQueryable. The extension methods below accomplish this, but then if I add another identical extension method, but on a different totally unrelated type I get ambiguous call compile errors. Why is that? Isn't the compiler smart enough to know which extension method works? I mean, only one of these calls is valid, why can't the compiler tell? Thanks a lot!

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);
}
like image 475
funGhoul Avatar asked Oct 10 '11 13:10

funGhoul


People also ask

What are extension methods in LINQ?

Extension Methods are a new feature in C# 3.0, and they're simply user-made pre-defined functions. An Extension Method enables us to add methods to existing types without creating a new derived type, recompiling, or modifying the original types.

What are extended methods in C#?

Extension methods enable you to "add" methods to existing types without creating a new derived type, recompiling, or otherwise modifying the original type. Extension methods are static methods, but they're called as if they were instance methods on the extended type.

What is extension method in MVC?

What is extension method? Extension methods in C# are methods applied to some existing class and they look like regular instance methods. This way we can "extend" existing classes we cannot change. Perhaps the best example of extension methods are HtmlHelper extensions used in ASP.NET MVC.

What is IEnumerable and IQueryable in LINQ?

In LINQ to query data from database and collections, we use IEnumerable and IQueryable for data manipulation. IEnumerable is inherited by IQueryable, Hence IQueryable has all the features of IEnumerable and except this, it has its own features. Both have its own importance to query data and data manipulation.


1 Answers

The overload rules don't take account of the constraints on methods that it's considering - it determines which overload is best and then validates that the constraints match.

The compiler is exactly following the rules of the C# specification.

Related blog posts:

  • Overloading and generic constraints (me)
  • Constraints are not part of the signature (Eric Lippert)
  • Evil code - overload resolution workaround (me - really nasty stuff, but fun)

EDIT: Note that using an "enumerableOrQueryable" is always going to convert your lambda expression to a delegate, not an expression tree. So if you wanted it to perform the logic differently for a database, you'd need a change anyway.

EDIT: Your idea also wouldn't work because you wouldn't get the same result type out anyway - if you call Where on a List<string>, the returned value isn't a List<string>.

What you can do is this, if you can introduce a new interface to 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);
}
like image 171
Jon Skeet Avatar answered Sep 23 '22 03:09

Jon Skeet