将List <anonymous type =“”>传递到需要C#</t> </an>中的List <t>的方法中

时间:2014-04-22 12:21:36

标签: c# generics

这可能吗?

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

var myCatObject = new CatData(cats);

这不起作用,因为编译器说它无法将cats转换为List<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);

4 个答案:

答案 0 :(得分:10)

您需要定义工厂方法。

在调用方法时推断泛型(如果可能),但在调用构造函数时则不推断。

所以加上这个:

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

像这样使用:

var data = CatData.Create(cats);

Eric Lippert还提供了一个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 :(得分: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);

答案 2 :(得分:0)

你不能使构造函数通用;要实例化一个通用类,你需要指定类参数。

但是,有一个解决方法:

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

//...
var myCatObject = cats.MakeCatData();

答案 3 :(得分:-4)

而不是使用var use dynamic。

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