我正在尝试使用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?
}
答案 0 :(得分:20)
好吧,因为在运行之前你不知道项目的实际类型,所以你不需要使用通用的IEnumerable<T>
接口;只使用非泛型的IEnumerable
(通用的一个继承自它):
private void WriteGenericCollection(object obj)
{
IEnumerable enumerable = (IEnumerable)obj;
foreach(object item in enumerable)
{
...
}
}
答案 1 :(得分:4)
你的问题充满了误解。让我们清理它们。
在下面的代码中,我们假设'obj'可以是类型
IEnumerable<>
或ICollection<>
或IList<>
。
如果确实如此,如果您知道可枚举的类型,那么编写该方法的更好方法是
private void WriteGenericCollection<T>(IEnumerable<T> obj)
{
// ...
}
我想将此System.Object转发给IEnumerable&lt;&gt;总是 (无论如何ICollection&lt;&gt;和IList&lt;&gt;继承自IEnumerable&lt;&gt;),所以 我想枚举集合并使用反射 写个别项目。
在谈论接口时,“继承”不是一个正确的术语;它也可能给你错误的想法。接口最好被认为是契约:在考虑实现接口时,您只能决定按照作者的意图实现它,或者根本不实现它。
某些接口是其他接口的超集;他们的合同说“除了合同所说的其他任何东西之外,实施者必须这样做”。但是,继承中没有任何共享实现,因为接口没有任何共享。
“向下转换”也不是您在该方法中所做的正确术语。向下转换意味着转向更加派生的类;还有一个界面:
// Note: the method is still generic!
private void WriteGenericCollection<T>(object obj)
{
var casted = (IEnumerable<T>)obj;
}
我想到将对象向下转换为非通用的IEnumerable,但是 以为这会导致不必要的对象装箱 让我们说IEnumerable的实际实例...我在想什么?
当且仅当对象是IEnumerable<T>
且其中T
是value type(数字类型,bool
时才会发生 ,enum
或struct
)。如果对象为某些已知的IEnumerable<T>
实现T
,那么您可以简单地将其强制转换为该T
。如果IEnumerable
未知,则转换为非通用{{1}}并获取可能的性能命中(在任何情况下都无法绕过它)。
如果您知道关于对象的 nothing ,您只需要使用反射(在这种情况下,您当然还需要为无法枚举的对象制定计划,否则为什么允许将它们传递给你的方法首先?)。