Generics C泛型:泛型类型推断的失败意味着我不能使用匿名类型

Generics C泛型:泛型类型推断的失败意味着我不能使用匿名类型,generics,c#-3.0,type-inference,Generics,C# 3.0,Type Inference,我有一个类导出器,它有一个通用方法,该方法接受IEnumerable并通过使用反射枚举其属性值来创建导出文档: public class Exporter { public string Export<T>(IEnumerable<T> enumerable) { //Implementation omitted } } 但是,当我如上所述调用新的导出重载时,泛型类型推断似乎不够聪明,无法推断ColumnDetails的泛

我有一个类导出器,它有一个通用方法,该方法接受IEnumerable并通过使用反射枚举其属性值来创建导出文档:

  public class Exporter
  {
    public string Export<T>(IEnumerable<T> enumerable)
    {
      //Implementation omitted
    }
  }
但是,当我如上所述调用新的导出重载时,泛型类型推断似乎不够聪明,无法推断ColumnDetails的泛型参数t应该与IEnumerable的泛型参数t相同。这意味着我必须指定List作为参数,因此我不能将其用于匿名集合

我对泛型和类型推断非常陌生。我想做的事可能吗?我是否需要以某种方式重新构造代码

编辑:这是我不能做的,因为Visual Studio需要ColumnDetails的通用参数,而我没有:

fooString = new Exporter().Export(foos.Select(x => new {TwiceTheHams = x.NumberOfHams * 2}),
                                          new List<ColumnDetails>
                                            {
                                              new ColumnDetails(x => x.TwiceTheHams, 12)
                                            });

这足以解决它吗

出口

那么您想传入一个列表>


在我看来,您需要一个通用的helper函数,该函数将接受IEnumerable参数并从中构造ColumnDetails对象列表。然后插入对该函数的调用,作为要导出的第二个参数。

类似的内容如何

anonList允许您拥有一个引用IEnumerable,CreateColumnDetails中的T foo允许编译器推断T是什么类型,允许您使用匿名类型作为T的值来构造对象


我看不出在提供的代码中使用泛型的任何原因。当您谈论匿名集合和匿名类型时,我认为您并不是指匿名类型-至少,您没有显示任何使用匿名类型导出的调用。如果你能给出一个失败的完整例子,那将非常有帮助。@Tomas:这意味着你可以提供任何对象的IEnumerable,例如一个业务实体,并将其导出到一种报告中。或Linq查询的输出。如果没有泛型,我看不出有什么方法可以做到这一点。@Jon:第二个代码块使用匿名类型的集合调用导出方法,这就是我所说的匿名集合。提供给它的IEnumerable被使用Select方法投影为匿名类型。@大卫:啊,我把Select调用误读为导出之后的调用。只显示匿名类型值的普通集合会更简单,例如new[]{new{X=X},new{X=y}。同样,一个完整的示例也会很有用。例如,当T为匿名时,如何创建列表?该代码目前适用于已知类型,如Foo。它不适用于匿名类型的集合。我明白了。匿名类型可能更难,因为您必须使用推断。您始终可以切换到导出,并让它在没有safet的情况下运行y net。@Micheal即使有点难看,也可以不使用动态。请参阅我答案的最新编辑。我解释得很糟糕。我的意思是,如果x是匿名类型的集合,我不能称为ExportIEnumerable x,IEnumerable y,因为这样我就无法实例化ColumnDetails集合。天哪,这是一大堆东西。@David,你能吗显示ColumnDetails是什么样子的?这可能会有帮助。这是可行的,但正如你所说的,它有点难看。我认为基本上我最初的想法是正确的-泛型类型推断没有走这么远。
public string Export<T>(IEnumerable<T> enumerable, IEnumerable<ColumnDetails<T>> columnDetails)
    {
      //Implementation omitted
    }
fooString = new Exporter().Export(foos,
                                      new List<ColumnDetails<Foo>>
                                        {
                                          new ColumnDetails<Foo>(x => x.Name, 12),
                                          new ColumnDetails<Foo>(x => x.NumberOfHams, 4),
                                        });
fooString = new Exporter().Export(foos.Select(x => new {TwiceTheHams = x.NumberOfHams * 2}),
                                          new List<ColumnDetails>
                                            {
                                              new ColumnDetails(x => x.TwiceTheHams, 12)
                                            });
fooString = new Exporter().Export<Foo>(foos,
     new List<ColumnDetails<Foo>>
          {
               new ColumnDetails<Foo>(x => x.Name, 12),
               new ColumnDetails<Foo>(x => x.NumberOfHams, 4),
          });
class Program
{
    public static ColumnDetails<T> CreateColumnDetails<T>(T foo, Func<T, object> func, int x)
    {
        return new ColumnDetails<T>(func, x);
    }
    static void Main(string[] args)
    {
        IEnumerable<Foo> foos = new List<Foo>();
        var anonList = foos.Select(x => new {TwiceTheHams = x.NumberOfHams*2});
        var fooString = new Exporter().Export(anonList,
                                      anonList.Select(y => CreateColumnDetails(y, z => z.TwiceTheHams, 12)));
    }
}
public class Exporter
{
    public string Export<T>(IEnumerable<T> enumerable, IEnumerable<ColumnDetails<T>> columnDetails)
    {
        return string.Empty;
    }
}

public class ColumnDetails<T>
{
    public ColumnDetails(Func<T, object> func, int x)
    {

    }
}
public class Foo
{
    public string Name { get; set; }
    public string NumberOfHams { get; set; }
}