我有一个按类型T和K
编写的方法public K Process<T,K> (IEnumerable<T> set)
{
//do stuff to set
}
我使用LINQ来获取我的数据的一些投影,我需要发送它进行处理
var dataSlice=records.Select(r => new { name = r.GetName(), id = r.GetId() });
string result = Process <?, string>(dataSlice);
我应该指定什么? (如果可以的话)
答案 0 :(得分:1)
您不能直接因为dataSlice
现在是匿名类型的集合,您可以尝试保留类型信息:
string result = Process(dataSlice);
有时编译器可以为您推断出正确的类型,它可以节省输入并且非常有用!
如果这不起作用,那么最好不要使用匿名类型并创建适当的类型来保存数据,或使用类似Tuple
的内容。
匿名类型很棒,但它们主要用于在linq查询之间传输数据,而不需要使用自定义类型。
虽然即使你可以通过编译器,你的Process方法也不知道它会得到什么,因此无法从dataSlice
中提取元素,所以最好按照自定义输入路线或使用前面所述的Tuple
。
答案 1 :(得分:1)
我喜欢这个简单的工具:
public static class Klass
{
public static Klass<T> Of<T>(){ return Klass<T>.instance; }
}
public class Klass<T>
{
public static Klass<T> instance = null;
}
现在你可以:
public K Process<T,K>(Klass<T> t, IEnumerable<K> items)
{
....
}
var aKey = Process(Klass.Of<string>(), mySetOfItems);
// aKey will be autotyped to a string
但请注意,这需要在Process方法中添加未使用的参数。此参数仅用于解决缺少的类型。这就是“实例”始终为空的原因。这个值并不重要,重要的是这个null是Klass类型。
但是,请注意,100%这样可以避免使用Process<string, ....>
中的显式类型参数,因为您不需要公开传递<string>
类型参数。因此,所有类型参数都绑定到参数,这允许copiler自动解析匿名类型,包括IEnumerable的项目。
编辑:我只记得一件事,虽然更复杂,更棘手。匿名类型完全是ducktyped。这意味着一个带有“string Key,int Value”的匿名类型与其他地方创建的第二个匿名类型完全属于同一个类,也就是“string Key,int Value”。这允许您创建此处描述的小辅助方法CastByExample。
通常,您无法“指定”匿名类型,因为它是未命名的,您无法写入它的名称。但是,由于这种珍贵的文章,这篇珍贵的文章展示了如何提供一个永不执行的lambda,它返回一个“示例”匿名对象,只是为了拦截它定义的匿名类型,以便该类型可以传递给表达链。非常的角落,但有趣的事情!
答案 2 :(得分:0)
简短的回答是,如果不重新设计方法,就不能这样做。 C#您必须指定所有类型参数或不指定。
一种选择是将您的Process
方法包装在单独的API中。
public class Processor<T>
{
public K Process<K>() { ... }
}
...
public Processor<T> CreateProcessor<T> (IEnumerable<T> set)
{
return new Processor<T>(set)
}
...
string result = CreateProcessor(dataSlice).Process<string>();
这是另一种选择,虽然它不那么直观,IMO:
public static class Process<K>
{
public static K From<T>(Ienumerable<T> set) { ... }
}
...
string result = Process<string>.From(dataSlice);