将对象转换为IEnumerable ,其中T未知

我正在尝试使用Reflection并遇到以下情况。

在下面的代码中,我们假设’obj’可以是IEnumerableICollectionIList

我想将此System.Object强制转换为IEnumerable always(因为ICollectionIList IEnumerable仍然从IEnumerableinheritance),所以我想枚举集合并使用reflection来编写单个项目。

这背后的动机是我只是想看看Serializers一般会如何序列化数据,所以我试图模拟这种情况,希望也能理解Reflection。

我想把对象转换为非通用的IEnumerable ,但是认为这会导致不必要的对象装箱,当我们说IEnumerable的实际实例时……我在想什么?

 private void WriteGenericCollection(object obj) { Type innerType = obj.GetType().GetGenericArguments()[0]; //Example: IEnumerable or IEnumerable Type generatedType = typeof(IEnumerable).MakeGenericType(innerType); //how could i enumerate over the individual items? } 

好吧,因为在运行之前你不知道项目的实际类型,所以你不需要使用通用的IEnumerable接口; 只使用非generics的IEnumerable (通用的inheritance自它):

 private void WriteGenericCollection(object obj) { IEnumerable enumerable = (IEnumerable)obj; foreach(object item in enumerable) { ... } } 

你的问题充满了误解。 让我们清理它们吧。

在下面的代码中,我们假设’obj’可以是IEnumerable<>ICollection<>IList<>

如果这是真的,并且如果你知道可枚举的类型,那么编写该方法的更好方法就是

 private void WriteGenericCollection(IEnumerable obj) { // ... } 

我想将此System.Object向下转换为IEnumerable <>始终(因为ICollection <>和IList <>从IEnumerable <>inheritance),所以我想枚举集合并使用reflection来编写单个项目。

在谈论接口时,“inheritance”不是一个正确的术语; 它也可能给你错误的想法。 接口最好被认为是契约 :在考虑实现接口时,您只能决定按照作者的意图实现它,或者根本不实现它。

有些接口是其他接口的超集; 他们的合同说“除了合同所说的任何其他内容之外,实施者必须这样做”。 但是在inheritance中从来没有共享实现,因为接口没有任何共享。

对于你在该方法中所做的事情,“向下转换”也不是正确的术语。 向下转换意味着转向更加派生的类; 还有一个界面:

 // Note: the method is still generic! private void WriteGenericCollection(object obj) { var casted = (IEnumerable)obj; } 

我想到将对象向下转换为非通用IEnumerable,但是认为这会导致不必要的对象装箱,当我们说IEnumerable的实际实例时……我在想什么?

当且仅当对象是IEnumerable才会发生拳击,其中T是值类型 (数字类型, boolenumstruct )。 如果对象为某些已知的T实现IEnumerable ,那么您可以简单地将其强制转换为该值。 如果T未知,则转换为非通用IEnumerable并采取可能的性能命中(在任何情况下都无法绕过它)。

如果您对对象一无所知,则只需要使用reflection(在这种情况下,您当然还需要为无法枚举的对象制定计划,否则为什么首先允许将它们传递给您的方法?)。