将泛型类型传递为T.

时间:2013-04-08 21:47:52

标签: c# .net generic-type-argument

我有一个按类型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);

我应该指定什么? (如果可以的话)

3 个答案:

答案 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);