1
List<T> objectList = GetList();

foreach (T setName in setNames)
{
 List<T> list = objectList.Where(x => x.QualificationID == setName).ToList();
 redisClient.SetAdd<string>("Qualification:" + setName, list.Select(x => x.ProductID).ToString());
}

In Line 3, T does not contain a definition for 'QualificationID' and no extension method 'QualificationID' accepting a first argument of Type T could be found.

Similarly in Line 4, T does not contain a definition for 'ProductID' and no extension method 'ProductID' accepting a first argument of Type T could be found.

how can we filter the list of generic object using linq?

EDIT : It is found not possible to filter the property value in a generic method until we specify the classtype. like extending method to,

method() where T : ClassType

as specified in the answers and comment.

4
  • 2
    Use a where T : SomeType generic type restraint in your method/class declaration. Commented May 1, 2017 at 7:51
  • Could you eloborate with an example? Commented May 1, 2017 at 7:55
  • I suspect list.Select(x => x.ProductID).ToString() will yield nothing usefull, as .Select() returns an IEnumerable<T>, who's .ToString() method returns the type name. Commented May 1, 2017 at 8:10
  • Post an minimal reproducible example. We ar least need to see the signature of GetList, and a basic idea of how you specify T. Commented May 1, 2017 at 8:52

2 Answers 2

4

Assuming that you have a base type BaseType that has the public members QualificiationID and ProductID, you can do the following:

void Foo<T>() where T : BaseType
{
    List<T> objectList = GetList();

    foreach (T setName in setNames)
    {
        List<T> list = objectList.Where(x => x.QualificationID == setName).ToList();
        redisClient.SetAdd<string>("Qualification:" + setName, list.Select(x => x.ProductID).ToString());
    }
}

This assumes that the generic type is specific to the method. If it's a class-level generic, simply move the where T : BaseType to the corresponding place in the class declaration instead.


As a secondary point, the ToString() part of your second .Select call probably isn't doing what you think it's doing. ToString will try to convert the object into a string, which by default will return the type name. That means that all you're getting out of it would be something along the lines of "System.Linq.IEnumerable+WhereSelectEnumerableIterator`1". In order to actually get a string from the LINQ, you will have to feed it to a string constructor and change it up a bit:

redisClient.SetAdd<string>("Qualification:" + setName, String.Join("", list.Select(x => x.ProductID.ToString()));
Sign up to request clarification or add additional context in comments.

2 Comments

in my case the T can be of any classType.
@KaarthickRaman Obviously it can't, since not every class type has the QualificationID or ProductID members.
0

The problem is that your compiler does not know that objects of type T has properties QualificationId and ProductId. You somehow have to tell it to the compiler.

The most generic way to do this, is to add a constraint to T informing the compiler that T has those two properties. This is done in a where clause

void MyFunc<T>(T obj) where T : ...

Instead of the dots, you can put a base class of which you know that it has those two properties. More generic is that you supply an interface. You promise, that whenever you use MyFunct, that the supplied obj is of a type T that implements the interface:

interface IMyInterface
{
    public int QualificationId {get;}
    public int ProductId {get;}
}

public void MyFunct<T>(List<T> objectList) where T: IMyInterface
{
    // here you know that any T implements IMyInterface,
    // and thus you can get QualificationId and ProductId

     List<T> list = objectList
        .Where(listElement => listElement.QualificationID == setName).ToList();
    redisClient.SetAdd<string>("Qualification:" + setName, 
        list.Select(listElement => listElement.ProductID).ToString());
}

The interface method is preferable above the base class method, because it gives you the opportunity to put use any T as long as it implements the interface, even if it has a different base class

As a side remark: I'm not sure what you want to do with SetAdd, but the result of your Select is probably a sequence of ProductIds. The ToString() of this sequence will describe the sequence, not the elements in the sequence. I'm fairly sure that is not what you want

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.