C# 将对象转换为 IEnumerable<T>,其中 T 未知
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/12169188/
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
Casting an object to IEnumerable<T> where T is not known
提问by Kiran Challa
I am trying to play with Reflection and ran into the following situation.
我正在尝试使用反射并遇到以下情况。
In the following code, let's assume that the 'obj' can be of types IEnumerable<>or ICollection<>or IList<>.
在下面的代码,让我们假设“OBJ”可以的类型IEnumerable<>或ICollection<>或IList<>。
I would like to cast this System.Object to IEnumerable<>always (as ICollection<>and IList<>inherit from IEnumerable<>anyway), so that i would like to enumerate over the collection and use reflection to write the individual items.
我想将此 System.Object 强制转换为IEnumerable<>始终(作为ICollection<>并IList<>从IEnumerable<>任何方式继承),以便我想枚举集合并使用反射来编写各个项目。
Motivation behind this is I am just trying to see if how would Serializers, in general, serialize data and so I am trying to simulate that situation in the hope to understand Reflection too.
这背后的动机是我只是想看看序列化程序通常如何序列化数据,所以我试图模拟这种情况,希望也能理解反射。
I thought of casting the object to non-generic IEnumerable, but thought that this would cause unnecessary boxing of objects, when let's say the actual instance of IEnumerable<int>...am I thinking right?
我想将对象强制转换为非通用 IEnumerable,但认为这会导致不必要的对象装箱,当让我们说IEnumerable<int>......的实际实例时,我想对吗?
private void WriteGenericCollection(object obj)
{
Type innerType = obj.GetType().GetGenericArguments()[0];
//Example: IEnumerable<int> or IEnumerable<Customer>
Type generatedType = typeof(IEnumerable<>).MakeGenericType(innerType);
//how could i enumerate over the individual items?
}
采纳答案by Thomas Levesque
Well, since you don't know the actual type of the items until runtime, you don't need to use the generic IEnumerable<T>interface; just use the non-generic one, IEnumerable(the generic one inherits from it):
好吧,因为直到运行时您才知道项目的实际类型,所以您不需要使用通用IEnumerable<T>接口;只需使用非泛型IEnumerable(泛型继承自它):
private void WriteGenericCollection(object obj)
{
IEnumerable enumerable = (IEnumerable)obj;
foreach(object item in enumerable)
{
...
}
}
回答by Jon
Your question is rife with misconceptions. Let's clear them up.
你的问题充满了误解。让我们把它们清理干净。
In the following code, let's assume that the 'obj' can be of types
IEnumerable<>orICollection<>orIList<>.
在下面的代码,让我们假设“OBJ”可以的类型
IEnumerable<>或ICollection<>或IList<>。
If that is true, and if you know the type of enumerable, a better way of writing the method would be
如果这是真的,并且如果您知道可枚举的类型,那么编写该方法的更好方法是
private void WriteGenericCollection<T>(IEnumerable<T> obj)
{
// ...
}
I would like to downcast this System.Object to IEnumerable<> always (as ICollection<> and IList<> inherit from IEnumerable<> anyway), so that i would like to enumerate over the collection and use reflection to write the individual items.
我想将此 System.Object 始终向下转换为 IEnumerable<>(因为 ICollection<> 和 IList<> 无论如何都继承自 IEnumerable<>),以便我想枚举集合并使用反射来编写各个项目。
"Inherit" is not a correct term when talking about interfaces; it could also give you the wrong ideas. Interfaces are best thought of as contracts: when considering to implement an interface, you can only decide to implement it as the author intended or not implement it at all.
在谈论接口时,“继承”不是一个正确的术语;它也可能给你错误的想法。接口最好被认为是契约:在考虑实现一个接口时,你只能决定按照作者的意图实现它,或者根本不实现它。
Some interfaces are supersets of other interfaces; their contracts say "implementors must do this in addition to whatever else thatcontract says". But there is never any sharing of implementation as is common in inheritance, because interfaces do not have any.
有些接口是其他接口的超集;他们的合同说:“实现者必须除了其他任何做到这一点的是契约说”。但是从来没有像继承中常见的任何实现共享,因为接口没有任何实现。
"Downcasting" is also not the correct term for what you are doing in that method. Downcasting means casting to a more derived class; there's also casting to an interface:
“向下转换”也不是您在该方法中所做的正确术语。向下转换意味着转换到派生程度更高的类;还有转换到接口:
// Note: the method is still generic!
private void WriteGenericCollection<T>(object obj)
{
var casted = (IEnumerable<T>)obj;
}
I thought of downcasting the object to non-generic IEnumerable, but thought that this would cause unnecessary boxing of objects, when let's say the actual instance of IEnumerable...am I thinking right?
我想将对象向下转换为非通用 IEnumerable,但认为这会导致不必要的对象装箱,当我们说 IEnumerable 的实际实例时......我想对吗?
Boxing would occur if and only ifthe object was an IEnumerable<T>where Tis a value type(a numeric type, a bool, an enumor a struct). If the object implements IEnumerable<T>for some known Tthen you can simply cast it to that. If Tis unknown then cast to non-generic IEnumerableand take the possible performance hit (there is no way around it in any case).
当且仅当对象是一个IEnumerable<T>whereT是值类型(数字类型、 a bool、 anenum或 a struct)时,才会发生装箱。如果该对象实现IEnumerable<T>了一些已知的,T那么您可以简单地将其转换为该对象。如果T未知,则转换为非泛型IEnumerable并采取可能的性能损失(在任何情况下都无法绕过它)。
You would only need to use reflection if you know nothingabout the object (in which case of course you also need to have a plan for objects that cannot be enumerated, otherwise why allow passing them to your method in the first place?).
如果您对对象一无所知,您只需要使用反射(在这种情况下,您当然还需要为无法枚举的对象制定计划,否则为什么首先允许将它们传递给您的方法?)。

