c#3.0-c#泛型:泛型类型推理失败意味着我不能使用匿名类型



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

  public class Exporter
  {
    public string Export<T>(IEnumerable<T> enumerable)
    {
      //Implementation omitted
    }
  }

由于泛型类型推断,我可以为其提供一个匿名集合类型。注意下面的方法调用中没有通用参数:

string fooString =
        new Exporter().Export(new List<Foo>()
                                {
                                  new Foo() {Name = "cats", NumberOfHams = 1},
                                  new Foo() {Name = "dogs", NumberOfHams = 8}
                                }
                       .Select(x => new { TwiceTheHams = x.NumberOfHams * 2 }));

我们都喜欢C#。但是,我想调整这个类,以便输入有关导出文档中列的更多信息,例如宽度。

我在导出类中创建了一个新方法,看起来像这样:

public string Export<T>(IEnumerable<T> enumerable, IEnumerable<ColumnDetails<T>> columnDetails)
    {
      //Implementation omitted
    }

理想情况下,语法应该是这样的,其中foos的类型是IEnumerable<Foo>:

fooString = new Exporter().Export(foos,
                                      new List<ColumnDetails<Foo>>
                                        {
                                          new ColumnDetails<Foo>(x => x.Name, 12),
                                          new ColumnDetails<Foo>(x => x.NumberOfHams, 4),
                                        });

然而,当我如上所述调用新的Export()重载时,泛型类型推断似乎不够聪明,无法推断ColumnDetails<T>的泛型参数T应该与IEnumerable的泛型参数T相同。这意味着我必须指定List<ColumnDetails<Foo>>作为参数,因此我不能将其用于匿名集合。

我对泛型和类型推理真的很陌生。我想做的事情可能吗?我需要以某种方式重组代码吗?

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

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

这足以修复它吗?

导出<Foo>

fooString = new Exporter().Export<Foo>(foos,
     new List<ColumnDetails<Foo>>
          {
               new ColumnDetails<Foo>(x => x.Name, 12),
               new ColumnDetails<Foo>(x => x.NumberOfHams, 4),
          });

这样的东西怎么样?

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

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

所以您想传入List<ColumnDetails< *anonymouse type with TwiceTheHams property* >>

在我看来,你需要一个通用的助手函数,它将接受一个IEnumerable<T>参数,并从中构造一个ColumnDetails对象列表。然后插入对该函数的调用,作为Export的第二个参数。

相关内容

最新更新