C#铸造问题

时间:2011-07-04 12:07:59

标签: c# casting

我有那段代码:

myDataGrid是传递给该方法的对象。我知道它是不同类型OvserveableCollection的类型。 我只需要将该对象强制转换为OvserveableCollection<T>(它实现IEnumerable接口)

//get element's type
Type entryType = (myDataGrid as IEnumerable).AsQueryable().ElementType; 

foreach (var item in (IEnumerable<entryType>)myDataGrid)
{}

但编译器不知道循环头中的entryType。为什么?

3 个答案:

答案 0 :(得分:5)

除非使用反射(Type / MakeGenericMethod()),否则不能将运行时MakeGenericType()实例用作泛型类型参数。不过我怀疑它会有所帮助!在这种情况下,要么使用非通用IEnumerable(无<T>)API,要么转换为已知的接口/子类,或者使用dynamic作为最后的手段。

可以也使用MakeGenericMethod()等,但这更复杂,几乎肯定会更慢。

例如:

foreach(object item in (IEnumerable)myDataGrid)
{
     // tada!
}

另一个技巧是使用dynamic来调用通用代码:

public void Iterate<T>(IEnumerable<T> data)
{
     foreach(T item in data) {...}
}
...
dynamic evil = myDataGrid;
Iterate(evil);

答案 1 :(得分:4)

您尝试使用Type 变量作为泛型类型的类型参数。泛型不是这样工作的 - 你必须使用编译时类型作为类型参数。 (如果您在通用方法中执行此操作,那么编译时类型本身可以是类型参数。)

很难知道如何建议您在不了解更多有关您的要求的情况下更改代码 - 您需要对这些项目做些什么?

答案 2 :(得分:1)

你不能转换为“运行时类型”...为了“写”实际实现该转换的指令,编译器需要Type ...这实际上只意味着Type必须在编译时间。

我发现围绕此限制的唯一方法是代码生成器(一种或另一种)“手动”生成IL指令以执行强制转换。除非我们对您的实际要求(和约束)了解很多,否则很难知道要推荐什么。

干杯。基思。