如何使用LINQ查询列表<t>

时间:2017-05-01 07:49:49

标签: c# linq generics

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());
}

在第3行中,T不包含'QualificationID'的定义,也没有可以找到接受Type T的第一个参数的扩展方法'QualificationID'。

同样在第4行, T不包含'ProductID'的定义,也没有扩展方法'ProductID'可以找到Type T的第一个参数。

我们如何使用linq过滤通用对象列表?

编辑:在指定classtype之前,发现无法在泛型方法中过滤属性值。 比如将方法扩展到,

method()其中T:ClassType

如答案和评论中所述。

2 个答案:

答案 0 :(得分:4)

假设您的基本类型<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <div class="imgcontainer"> <div style="background-image:url(http://placehold.it/500x340/0bf);"> Slide 1 </div> <div style="background-image:url(http://placehold.it/500x340/f0b);"> Slide 2 </div> <div style="background-image:url(http://placehold.it/500x340/b0f);"> Slide 3 </div> </div>包含公共成员BaseTypeQualificiationID,您可以执行以下操作:

ProductID

这假设泛型类型特定于该方法。如果它是类级泛型,只需将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()); } } 移动到类声明中的相应位置。

作为次要问题,第二次where T : BaseType来电的ToString()部分可能与您认为正在进行的操作无关。 .Select将尝试将对象转换为字符串,默认情况下将返回类型名称。这意味着所有你摆脱它的东西都是ToString的。为了从LINQ中实际获取字符串,您必须将它提供给字符串构造函数并稍微更改一下:

"System.Linq.IEnumerable+WhereSelectEnumerableIterator`1"

答案 1 :(得分:0)

问题是您的编译器不知道T类型的对象具有QualificationId和ProductId属性。你不得不告诉编译器。

执行此操作的最通用方法是向T添加约束,通知编译器T具有这两个属性。这是在where clause

中完成的
void MyFunc<T>(T obj) where T : ...

您可以放置​​一个您知道它具有这两个属性的基类,而不是点。更通用的是你提供一个接口。您保证,无论何时使用MyFunct,提供的obj都是实现接口的类型T:

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());
}

接口方法优于基类方法,因为只要它实现了接口,它就让你有机会使用任何T,即使它有不同的基类

作为旁注:我不确定你想用SetAdd做什么,但你的Select的结果可能是一系列ProductIds。此序列的ToString()将描述序列,而不是序列中的元素。我很确定这不是你想要的