tags:

views:

802

answers:

3

C#, .net 3.5

I am trying to create a base class that has a generic method. Classes that inherit from it should specify the method's type(s).

The premise for this is for creating classes that manage filtering.

So I have:

 public abstract class FilterBase {
   //NEED Help Declaring the Generic method for GetFilter
   //public abstract IQueryable<T> GetFilter<T>(IQueryable<T> query);
 }

 public class ProjectFilter:FilterBase {
   public IQueryable<Linq.Project> GetFilter(IQueryable<Linq.Project> query) {
     //do stuff with query
     return query;
   }
 }

 public class ProjectList {
   public static ProjectList GetList(ProjectFilter filter) {
     var query = //....Linq code...

     query = filterCriteria.GetFilter(query); 

   }

 }

Think it is something simple, but I can't get the syntax right in FilterBase for the GetFilter abstract method.

EDIT

Ideally, would like to keep only the method as generic and not the class. If not possible, then please let me know..

+7  A: 

Make the FilterBase class itself generic.

public abstract class FilterBase<T>
{
    public abstract IQueryable<T> GetFilter(IQueryable<T> query);
}

This would enable you to create your ProjectFilter class like this:

public class ProjectFilter : FilterBase<Linq.Project>
{
    public override IQueryable<Linq.Project> GetFilter(IQueryable<Linq.Project> query)
    {
        //do stuff with query
        return query;
    }
}
Mark Seemann
that works, do I have to make the class generic though? Can't I just keep the method generic? Reason I ask is there may be multiple GetFilter's for the same class that take a different IQueryable<T> than 'Linq.Project'
B Z
@B Z: You can make only the method generic, but then it will have to stay generic until invoked. You can't derive from the non-generic class and assign the generic type on the method as you attempt in your question. The caller would have to supply the type to the method in that case.
Mark Seemann
@Mark - thx. Seems like a limitation to me? Do you know if there is further explanation out there? Maybe in Jon Skeet's C# In Depth?
B Z
@B Z: If the class isn't generic, the signature of the method contains unbounded generics. What you try to do is to override the method with constructed types at the same time. That more or less corresponds to attempting to override a member and change its signature at the same time - that's just not allowed, generics or no generics. Jon Skeet's book has an entire chapter on generics, but whether it answers your question exactly I can't say.
Mark Seemann
Your code isn't syntactically correct. GetFilter should not itself be generic, and you are missing an "override" in ProjectFilter.
Bryan Watts
@Bryan Watts: Thanks for pointing that out. I've edited the answer to have correct syntax.
Mark Seemann
No worries +1
Bryan Watts
@BZ: This is not a limitation. From your description, the abstract method is obviously not generic because it only allows one set of types. Making the method generic is a complete contradiction of its public contract, so you shouldn't even be pondering techniques to do so. If you need a non-generic base type, make `FilterBase<T>` derive from a `FilterBase` type.
280Z28
+2  A: 
 public abstract class FilterBase<T> {
    public abstract IQueryable<T> GetFilter<T>(IQueryable<T> query);
 }
Bob
+1  A: 

Of course, you can have an abstract generic method:

public abstract class FilterBase {
    public abstract IQueryable<T> GetFilter<T>(IQueryable<T> query);
}

The problem is that it doesn't mean what you want. It can be called for any T. In particular, the following must work, since ProjectFilter derives from FilterBase:

FilterBase fb = new ProjectFilter(...);
IQueryable<string> query = ...;
IQueryable<string> filter = fb.GetFilter<string>(query);

So FilterBase can't just implement GetFilter<Linq.Project>. It needs to implement GetFilter<string>, GetFilter<int>, etc.; in short, GetFilter<T>. So you can see it isn't a limitation.

Alexey Romanov