本文介绍了C#泛型:泛型类型推断失败意味着我不能使用匿名类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

  public class Exporter 
{
public string Export< T>(IEnumerable< T> enumerable)
{
//执行省略
}
}

由于通用类型推断,我可以提供一个匿名集合类型。请注意以下方法调用中缺少泛型参数:

  string fooString = 
Exporter()。Export (新列表< Foo>()
{
new Foo(){Name =cats,NumberOfHams = 1},
new Foo(){Name =dogs,NumberOfHams = 8}
}
。选择(x => new {TwiceTheHams = x.NumberOfHams * 2}));

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



我在导出类中创建了一个新方法,如下所示:

  public string Export< T>(IEnumerable< T> enumerable,IEnumerable< ColumnDetails< T> columnDetails)
{
//执行省略
}

理想情况下,语法是这样的,其中 foos 是键入 IEnumerable< Foo>
$ b

  fooString = new Exporter()。新增ColumnDetails< Foo>(x => x.Name,12),
新列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>
{
新ColumnDetails(x => x.TwiceTheHams,12)
});


解决方案

这个怎么样?

b
$ b

anonList 可以让你有一个引用 IEnumerable< anontype> code> T foo 在 CreateColumnDetails< T> 中可以让编译器推断T是什么类型,从而允许您使用匿名类型为 T

  class程序
{
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 =新列表< 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))); (IEnumerable< T> enumerable,IEnumerable< ColumnDetails< T>> columnDetails)


public class Exporter
{
public string Export< T>
{
return string.Empty;
}
}

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

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


I have a class Exporter which has a generic method which accepts an IEnumerable<T> and creates an export document by enumerating its property values using reflection:

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

Because of generic type inference, I can supply this with an anonymous collection type. Note the absence of the generic parameter in the method call below:

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

We all love C#3. However, I would like to adapt this class so that I can enter more information about the columns in the export document, for example the width.

I have created a new method in the export class which looks like this:

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

Ideally, the syntax would be like this, where foos is of type 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),
                                        });

However, when I call the new Export() overload as above, the generic type inference doesn't seem to be clever enough to infer that the generic parameter T for the ColumnDetails<T> should be the same as the generic parameter T for the IEnumerable. This means that I must specify List<ColumnDetails<Foo>> as the parameter, and therefore I cannot use this with anonymous collections.

I'm really new to generics and type inference. Is what I'm trying to do possible? Do I need to restructure the code somehow?

Edit: this is what I cannot do, because Visual Studio needs the generic parameter for ColumnDetails, which I don't have:

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

How about something like this?

The anonList lets you have a reference IEnumerable<anontype> and the T foo in CreateColumnDetails<T> lets the compiler infer what type T is, allowing you to construct the object with an anonymous type as the value of 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; }
}

这篇关于C#泛型:泛型类型推断失败意味着我不能使用匿名类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-27 04:47