0

I have a collection IQueryable<Car> and I want to pass it into a generic function that takes in as a parameter IQueryable<T>, something like (which is sitting in a base class).

public abstract class  BaseController<T> : ControllerBase  where T : BaseObj, new()
{
    public IQueryable<T> FilterEntities(IQueryable<T> entities)
    {
    }
}

What is the right way to pass this in? Cast? Safety cast?

4
  • 1
    Is this method defined in a generic class? Because your method isn't generic, it doesn't define any type parameters Commented Apr 16, 2012 at 11:57
  • it depends what you want to do with it after... Commented Apr 16, 2012 at 11:57
  • 1
    If you're only going to be passing in instances of IQueryable<Car>, why would you make this method generic? Commented Apr 16, 2012 at 12:00
  • Not sure what you want to do with the BaseController but I would try to avoid using them if possible. For example if you want to use normal controllers, web api controllers and async controllers in your project, you would need to then create three base controllers and duplicate some code. Instead you should look at Global or Controller level filters. Commented Apr 16, 2012 at 16:02

3 Answers 3

2

your problem is that your method isn't generic, the class is. Notice there' no <T> after then method name, than mean you have to pass in an IQueryable of what ever was yoused for the type argument for the class.

E.g if the object was instantiated like this:

new BaseController<BaseObject>(..) //ignoring that BaseController is abstract

you'd need to pass an IQueryable<BaseObject> so in your case where you wish to pass in an IQueryable<Car> the type of controller needs to derive from BaseController<Car>

If on the other hand you wish the method to be generic change the signature of the method to

public IQueryable<TElement> FilterEntities<TElement>
            (IQueryable<TElement> entities)

that does not include the type contraint on T you have on the type parameter for the class. If this is should be enforced for the generic method the signature needs to be:

public IQueryable<TElement> FilterEntities<TElement>(IQueryable<TElement> entities) 
            where TElement : BaseObj, new()

EDIT If you wish to have a "default" method that simply uses T as the type argument you will have to implement it as a non generic method just as you have in your code so the class would be:

  public abstract class  BaseController<T> : ControllerBase  
                where T : BaseObj, new()
  {

     public IQueryable<T> FilterEntities(IQueryable<T> entities)
     {
            return FilterEntities<T>(entities);
     }

     public IQueryable<TElement> FilterEntities<TElement>(IQueryable<TElement> entities) 
                where TElement : BaseObj, new()
  }
Sign up to request clarification or add additional context in comments.

2 Comments

Is there anyway to have both the class generic and the method generic as most of the time i want the method to use the T from the class but I want to reuse this same code sometimes when i want to pass in a type that is not the same T as the class ? I get a warning . ."Type parameter has the same name as outer type name . ."
@leora you'll have to write a bit of boiler plate code for that
1
public IQueryable<TQueryable> FilterEntities<TQueryable>(
    IQueryable<TQueryable> entities)
{
}

You need to make the method a generic method (the <T> after the function name before the parens tells the compiler the method is generic).

The type parameter TQueryable of the method differs from the class type. If you don't want it to your method signature should be fine.

3 Comments

and you should choose a different type argument name than the one used for the class
@Rune FS - i see that i get a warning if i choose the same name "Type param name is the same as outer type" . . is this a problem as i want to use the method in both ways if possible . .
@leora the type parameter from the class will be overriden with the one from the method (that is in the signature of the method and in the implementation T as it refers to the type used for the class is inaccessible and it does not solve the "default type" you're looking for
0

Define the FilterEntities as below

public IQueryable<T> FilterEntities<T>(IQueryable<T> entities)
{
}

Now you can pass IQueryable as below

    IQueryable<Car> x = null; //Initialize it
    FilterEntities<Car>(x);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.