问题描述
我有一个类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()$ c $如上所述,通用类型推断似乎不足以推断
应该与 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#泛型:泛型类型推断失败意味着我不能使用匿名类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!