0

为了节省内存,我定义了一些类似记录的结构并将它们的实例存储在数组中,如以下代码所示:

struct Foo
{
    readonly char _bar;
    readonly int _baz;
    // other probable fields ...
    public char Bar{get{return _bar;}}
    public int Baz{get{return _baz;}}

    public Foo(char bar, int baz){_bar = bar; _baz = baz;}
}

static void Main ()
{
    Foo[] arr = new Foo[1000000];
    int baz;
    for(var i = 1000000; i-- > 0;){ arr[i] = new Foo('x',42); }
    for(var i = 1000000; i-- > 0;)
    { 
        baz = arr[i].Baz; //Will the Foo obj resides at arr[i] be copied?
    }
}

我知道如果上面的东西是用 C/C++ 实现的,复制就不会发生,但我不确定 C#,如果我用 替换Foo[]怎么List<Foo>办?C# 没有返回引用的机制,所以理论上,如果不涉及返回值优化,索引器将返回引用类型的指针(4 字节)或值类型的整个副本。那么,谁能告诉我,.NET/MONO jit 是否可以保证避免这种荒谬的复制?

4

2 回答 2

3

不,该值不会被复制 -arr[i]被归类为变量,因此Baz将“就地”获取。我花了一段时间才弄清楚如何验证这一点,但这几乎可能的,通过使属性更改数组中的值......

using System;

public struct Foo
{
    private int field;

    public int Value
    {
        get
        {
            Test.array[0].field = 10;
            return field;
        }
    }
}    

public class Test
{
    public static Foo[] array = new Foo[1];

    static void Main()
    {
        Console.WriteLine(array[0].Value); // Prints 10
    }
}

请注意,您对“Foo obj”的评论在 C# 中有些误导 - 这里没有对象;只有一个 type 的值Foo

于 2012-11-05T07:43:43.230 回答
1
 for(var i = 1000000; i-- > 0;)
    { 
        baz = arr[i].Baz; //Will the Foo obj resides at arr[i] be copied?
    }

没有。要复制Foo对象,您实际上必须将 Foo 对象分配给另一个变量。

Foo foo = arr[i] ;//would copy the struct at arr[i] into foo. I'm pretty sure it is this case with C/C++.
于 2012-11-05T07:43:00.987 回答