基本上我试图用一个通用数组包装一个IEnumerable
并且仍然能够修改原始集合中的值,当我只修改它们的内部字段时,这适用于引用类型,但是在使用时值类型或尝试替换它似乎不起作用的元素。
例如:
// Original enumerable
var test = new List<int>(new int[] {
1,
2,
3
});
// Array wrapper
var test2 = test.ToArray();
test2[0] = 100; // Does not change test[0]
// Don't want to use pointers, but as a test
unsafe
{
int* test3 = &test2[0];
*test3 = 100; // Still does not change test[0]
}
所以我想知道是否有某种方法可以创建一个值类型IEnumerable
的数组包装器,它允许修改原始集合值?
我需要这样做的原因是类与FORTRAN95代码共享,并且由于对.NET数组的有限编译器支持,我不能从System.Array
继承任何内容
答案 0 :(得分:3)
Enumerable.ToArray()
没有&#34;包裹&#34;数组中的可枚举:它遍历可枚举,创建一个数组。它几乎相当于:
public static T[] ToArray<T>( this IEnumerable<T> source )
{
List<T> list = new List<T>() ;
foreach( T item in source )
{
list.Add(item) ;
}
T[] value = list.ToArray() ;
return value ;
}
所以如果你做这样的事情:
int[] foo = PopulateSource() ;
int[] bar = foo.ToArray() ; // Enumerable.ToArray()
说
foo[3] = int.MinValue ;
无论数组是否包含值类型或引用类型,都不会影响bar[3]
。
但是,如果您使用参考类型,
Widget[] foo = PopulateSource() ;
Widget[] bar = foo.ToArray() ; // Enumerable.ToArray()
并说出类似
的内容foo[3].Gadget = new Gadget("Pancake Turner") ;
然后更改将反映在foo[3]
和bar[3]
中,因为两个数组插槽都是对同一Widget
实例的引用。
此外,您无法在数组中包装内容,因为即使System.Array
不是sealed
:
public abstract class Array :
ICloneable, IList, ICollection, IEnumerable,
IStructuralComparable, IStructuralEquatable
它是一个特殊的类,不能继承。所以像这样:
class Widget : System.Array
{
}
产生此编译器错误
error CS0644: 'ConsoleApplication2.Program.Widget' cannot derive from special class 'System.Array'
您可以做的是为原始对象创建一个包装器,它提供类似于数组的语义,实现IList
和IList<T>
。