2017-05-01 49 views
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()); 
} 

在3號線到查詢列表 ,T不包含「QualificationID」的定義,並沒有擴展方法「QualificationID」接受類型T的第一個參數可以發現。 如何使用LINQ

同樣在第4行中, T沒有包含'ProductID'的定義,也沒有找到接受Type T的第一個參數的擴展方法'ProductID'。

如何使用LINQ我們篩選通用對象的名單?

編輯:直到我們指定類型時,才發現無法過濾泛型方法中的屬性值。 像延伸方法,

()的方法,其中T:類類別

如答案和註釋指定。

+2

在方法/類聲明中使用'where T:SomeType'通用類型限制。 – Abion47

+0

你能舉個例子嗎? –

+0

我懷疑'list.Select(x => x.ProductID).ToString()'將不會產生任何有用的結果,因爲'.Select()'返回'IEnumerable ',誰是.'ToString()'方法返回類型名稱。 –

回答

3

假設你有一個基本類型BaseType具有公共成員QualificiationIDProductID,你可以做到以下幾點:

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改爲在類聲明中的相應位置。


作爲第二點,你的第二個電話.SelectToString()部分可能不是做什麼,你覺得它在做什麼。 ToString會嘗試將對象轉換爲一個字符串,默認情況下會返回類型名稱。這意味着你所得到的所有東西都會沿着"System.Linq.IEnumerable+WhereSelectEnumerableIterator`1"的方向行進。爲了實際得到的LINQ一個字符串,則必須將其提供給一個字符串構造函數,改變它一點:

redisClient.SetAdd<string>("Qualification:" + setName, String.Join("", list.Select(x => x.ProductID.ToString())); 
+0

在我的情況下,T可以是任何classType。 –

+2

@KaarthickRaman顯然它不能,因爲不是每個類都有'QualificationID'或'ProductID'成員。 – Abion47

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()將描述序列,而不是序列中的元素。我相當肯定這不是你想要的