我正在尝试使用Reflection并遇到以下情况.
在下面的代码中,我们假设'obj'可以是类型IEnumerable<>或ICollection<>或IList<>.
我想将此System.Object强制转换为IEnumerable<>(始终如此)ICollection<>并IList<>继承IEnumerable<>,以便我想枚举集合并使用反射来编写单个项目.
这背后的动机是我只是想看看Serializers如何序列化数据,所以我试图模拟这种情况,希望也能理解Reflection.
我想把对象转换为非通用的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?
}
Run Code Online (Sandbox Code Playgroud)
Tho*_*que 22
好吧,因为在运行之前你不知道项目的实际类型,所以你不需要使用通用IEnumerable<T>接口; 只使用非泛型的IEnumerable(通用的一个继承自它):
private void WriteGenericCollection(object obj)
{
IEnumerable enumerable = (IEnumerable)obj;
foreach(object item in enumerable)
{
...
}
}
Run Code Online (Sandbox Code Playgroud)
你的问题充满了误解。让我们把它们清理掉吧。
在下面的代码中,我们假设 'obj' 的类型可以是
IEnumerable<>orICollection<>或IList<>。
如果这是真的,并且如果您知道可枚举的类型,那么编写该方法的更好方法是
private void WriteGenericCollection<T>(IEnumerable<T> obj)
{
// ...
}
Run Code Online (Sandbox Code Playgroud)
我想始终将此 System.Object 向下转换为 IEnumerable<> (因为 ICollection<> 和 IList<> 无论如何都继承自 IEnumerable<>),以便我想枚举集合并使用反射来写入各个项目。
在谈论接口时,“继承”并不是一个正确的术语。它也可能会给你错误的想法。接口最好被视为契约:在考虑实现接口时,您只能决定按照作者的意图实现它或根本不实现它。
有些接口是其他接口的超集;他们的合同规定“除了合同规定的其他内容之外,实施者还必须这样做”。但是,继承中常见的实现共享从来不存在,因为接口没有任何实现共享。
“向下转型”也不是您在该方法中所做的事情的正确术语。向下转型意味着转型为更派生的类;还有转换到接口:
// Note: the method is still generic!
private void WriteGenericCollection<T>(object obj)
{
var casted = (IEnumerable<T>)obj;
}
Run Code Online (Sandbox Code Playgroud)
我想过将对象向下转换为非泛型 IEnumerable,但认为这会导致不必要的对象装箱,当我们说 IEnumerable 的实际实例时......我想对了吗?
当且仅当IEnumerable<T>对象是T值类型(数字类型、 a bool、 anenum或 a )时才会发生装箱struct。如果该对象实现了IEnumerable<T>某些已知的对象T,那么您可以简单地将其强制转换为该对象。如果T未知,则转换为非泛型IEnumerable并承受可能的性能影响(在任何情况下都没有办法解决)。
如果您对对象一无所知,则只需要使用反射(当然在这种情况下,您还需要对无法枚举的对象制定计划,否则为什么首先允许将它们传递给您的方法?)。