2014-04-22 17 views
2

這可能嗎?通過列表<匿名類型>到方法需要列表中<T> C#

var cats = catsource.Select(c => new 
{ 
    CatId = c.catId, 
    Name = c.Name, 
}).ToList(); 

var myCatObject = new CatData(cats);

這不起作用,因爲編譯器說,它不能轉換成catsList<T>

cats是一個匿名類型,CatData是:

public class CatData<T> 
{ 
    public int total; 
    public int records; 
    public List<T> records; 

    public CatData(List<T> dataObjects, int totalRecords, int numberOfRows) 
    { 
     total = (int)Math.Ceiling((double)totalRecords/numberOfRows); 
     records = totalRecords; 
     rows = dataObjects; 
    } 
} 

任何想法?


編輯:

所以我做了這個代碼,但仍有一個問題:

public class CatData 
{ 
    public int total; 
    public int records; 
    public List<T> rows; 

    private CatData(List<T> dataObjects, int totalRecords, int numberOfRows) 
    { 
     total = (int)Math.Ceiling((double)totalRecords/numberOfRows); 
     records = totalRecords; 
     rows = dataObjects; 
    } 

    public static CatData<T> Create(List<T> dataObjects, int totalRecords, int numberOfRows) 
    { 
     return new CatData<T>(dataObjects, totalRecords, numberOfRows); 
    } 
} 

此代碼對的<T>每個實例的錯誤說

無法解析符號T

如果我改變類是public class CatData<T>它編譯,但我不能有這樣的代碼:因爲它說

的類型參數的數目不正確

CatData.Create(records, totalRecords, rows);


更新來解釋我想要什麼:

我想創建具有匿名類型對象的列表

var someList = someCollection.Select(new { ... });

我想創建一個對象,它存儲他們作爲List<anonymous>

var myObject = new myObject(someList, 5);

所以我可以做:

myObject.someValue; // 5 (stored it in the constructor) myObject.myList.Count(); // can count how many anonymous objects are in there

也許我應該只是將其存儲爲List<object>


我真的不明白,也許我只是有點太厚。我剛剛結束了這個:

public CatData(List<object> dataObjects, int totalRecords, int numberOfRows)作爲我的構造函數。

var catData = new CatData(records.Cast<object>().ToList(), totalRecords, rows);

+1

什麼是'CatData'發佈其定義 –

+6

什麼是'T'在CatData構造? –

+0

從什麼時候構造函數允許泛型參數? – Crono

回答

10

您需要定義工廠方法。

在調用方法時推斷(如果可能)泛型,但在調用構造函數時不泛化。

所以補充一點:

public static class CatData 
{ 
    public static CatData<T> Create<T>(List<T> cats) 
    { 
     return new CatData<T>(cats); 
    } 
} 

像這樣使用:

var data = CatData.Create(cats); 

埃裏克利珀還提供了一個answer here講一些爲什麼,這是不允許的考慮。

隨着新版本Roslyn compiler的推出,新功能可能會出現更好的機會,因爲這意味着1次更改可以應用於多種語言,並且更容易實現,這可能會爲本次討論帶來新的生機。作爲apparently supporting type inference on generic constructor parameters is now being considered: DamienG's blog, Probable C# 6.0 features illustrated


由於似乎是作爲是否這一招確實有效與否,這裏有一個完整的LINQPad程序,演示了一些困惑:

void Main() 
{ 
    var test = new[] 
    { 
     new { name = "Test", id = 42 }, 
     new { name = "Test 2", id = 17 } 
    }.ToList(); 
    CatData.Create(test); 
} 

public class CatData<T> 
{ 
    public CatData(List<T> list) 
    { 
    } 
} 

public static class CatData 
{ 
    public static CatData<T> Create<T>(List<T> list) 
    { 
     return new CatData<T>(list); 
    } 
} 

這工作得很好,說明在相同的命名空間和程序集中同時使用具有相同類名的靜態非泛型類和泛型類是完全合法的。

在.NET框架中應該有充足的證據證明這一點,因爲Tuple存在多個版本。當你調用方法

+1

這已經解決了這個問題。似乎有點奇怪,爲什麼它不適用於構造函數,但我確定有一個巧妙的原因, – NibblyPig

+0

實際上可能講得太快了,而沒有將類定義爲'CatData ',它似乎不起作用。 – NibblyPig

+0

請參閱[Eric Lipperts答案](http://stackoverflow.com/questions/3570167/why-cant-the-c-sharp-constructor-infer-type/3570360#3570360)。 –

-4

而不是使用var use dynamic。

dynamic cats = catsource.Select(c => new 
{ 
    CatId = c.catId, 
     Name = c.Name, 
}).ToList(); 
2

泛型類型推斷的工作,所以你應該創建一個工廠方法:

public static class CatData 
{ 
    public static CatData<T> Create<T>(List<T> dataObjects, int totalRecords, int numberOfRows) 
    { 
     return new CatData<T>(dataObjects, totalRecords, numberOfRows); 
    } 
} 

,現在你可以這樣做:

var cats = catsource.Select(c => new 
{ 
    CatId = c.catId, 
    Name = c.Name, 
}).ToList(); 

var myCatObject = CatData.Create(cats, cats.Length, cats.Length); 
0

你不能讓一個構造通用的;並實例化一個你需要指定類參數的泛型類。

但是,有一個解決方法:

public static class CatDataHelper 
{ 
    public static CatData<T> MakeCatData<T>(this List<T> list) 
    { 
     return new CatData<T>(list); 
    } 
} 

//... 
var myCatObject = cats.MakeCatData(); 
相關問題