C# 将 IEnumerable 转换/转换为 IEnumerable<T>
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/812673/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Convert / Cast IEnumerable to IEnumerable<T>
提问by andleer
I have a class (A web control) that has a property of type IEnumerable and would like to work with the parameter using LINQ.
我有一个类(一个 web 控件),它有一个 IEnumerable 类型的属性,并且想使用 LINQ 处理参数。
Is there any way to cast / convert / invoke via reflection to IEnumerable<T> not knowing the type at compile time?
有没有办法通过反射将/转换/调用转换为 IEnumerable<T> 在编译时不知道类型?
Method void (IEnumerable source)
{
var enumerator = source.GetEnumerator();
if (enumerator.MoveNext())
{
var type = enumerator.Current.GetType();
Method2<type>(source); // this doesn't work! I know!
}
}
void Method2<T>(IEnumerable<T> source) {}
采纳答案by Jon Skeet
Does your Method2
really care what type it gets? If not, you could just call Cast<object>()
:
你Method2
真的关心它是什么类型吗?如果没有,你可以打电话Cast<object>()
:
void Method (IEnumerable source)
{
Method2(source.Cast<object>());
}
If you definitely need to get the right type, you'll need to use reflection.
如果您确实需要获得正确的类型,则需要使用反射。
Something like:
就像是:
MethodInfo method = typeof(MyType).GetMethod("Method2");
MethodInfo generic = method.MakeGenericMethod(type);
generic.Invoke(this, new object[] {source});
It's not ideal though... in particular, if source isn't exactlyan IEnumerable<type>
then the invocation will fail. For instance, if the first element happens to be a string, but source is a List<object>
, you'll have problems.
但它并不理想……特别是,如果源不完全是一个,IEnumerable<type>
那么调用将失败。例如,如果第一个元素恰好是一个字符串,而 source 是 a List<object>
,你就会遇到问题。
回答by Brian Genisio
You probably want to refactor your code to use IEnumerable.Cast<T>
您可能想要重构您的代码以使用 IEnumerable.Cast<T>
Use it like this:
像这样使用它:
IEnumerable mySet = GetData();
var query = from x in mySet.Cast<int>()
where x > 2
select x;
回答by Michael Anderson
This is years later, but I solved the List<Object>
problem.
这是多年后,但我解决了这个List<Object>
问题。
void Method(IEnumerable source)
{
var enumerator = source.GetEnumerator();
if (enumerator.MoveNext())
{
MethodInfo method = typeof(MyClass).GetMethod("Method2");
MethodInfo generic;
Type type = enumerator.Current.GetType();
bool sameType = true;
while (enumerator.MoveNext())
{
if (enumerator.Current.GetType() != type)
{
sameType = false;
break;
}
}
if (sameType)
generic = method.MakeGenericMethod(type);
else
generic = method.MakeGenericMethod(typeof(object));
generic.Invoke(this, new object[] { source });
}
}
回答by luksan
With .NET 4 you can just cast source
to dynamic
before passing it to method. This will cause the correct generic overload to be resolved at runtime without any ugly reflection code:
在.NET 4中你只可以投source
给dynamic
它传递给方法之前。这将导致在运行时解析正确的泛型重载,而无需任何难看的反射代码:
void Method(IEnumerable source)
{
var enumerator = source.GetEnumerator();
if (enumerator.MoveNext())
{
Method2((dynamic)source);
}
}
As with Jon's second solution, this will only work if your source is actually an IEnumerable<T>
. If it is a plain IEnumerable
then you'll need to create another method that converts it to the correct IEnumerable<T>
type, as in the following solution:
与 Jon 的第二个解决方案一样,这仅在您的源实际上是IEnumerable<T>
. 如果它是一个普通的,IEnumerable
那么你需要创建另一个方法来将它转换为正确的IEnumerable<T>
类型,如以下解决方案:
IEnumerable<T> Convert<T>(IEnumerable source, T firstItem)
{
// Note: firstItem parameter is unused and is just for resolving type of T
foreach(var item in source)
{
yield return (T)item;
}
}
void Method(IEnumerable source)
{
var enumerator = source.GetEnumerator();
if (enumerator.MoveNext())
{
dynamic firstItem = enumerator.Current;
dynamic typedEnumerable = Convert(source, firstItem);
Method2(typedEnumerable);
}
}