无法修改"List.this[int]"的返回值,因为它不是变量

使用List写代码的时候遇到了一个“怪异”的现象,无法修改List中对象的属性值。
下面就具体使用代码一起来看一下:
private void test()
{
    List list = new List();
    list.Add(new Vector3(1, 0, 0));
    list.Add(new Vector3(2, 0, 0));
    list.Add(new Vector3(3, 0, 0));

    // 使用下面这句代码的时候就会出现编译错误
    // 错误提示如下
    // 无法修改"List.this[int]"的返回值,因为它不是变量
    list[0].x = 4f;
}

这个就让人比较纳闷了,然后我们尝试使用一下Vector3中的Set方法
private void test()
{
    List list = new List();
    list.Add(new Vector3(1, 0, 0));
    list.Add(new Vector3(2, 0, 0));
    list.Add(new Vector3(3, 0, 0));

    Debug.Log("list[0] = " + list[0]);
    list[0].Set(4f, 0, 0);
    Debug.Log("list[0] = " + list[0]);
}

这次编译器不会报出任何错误,但是通过打印可以发现,两次打印的结果是一样的,O~Shit!
这和我们平常的使用不太一样啊,哪里出问题了呢?
好吧,既然这样,咱们就继续探索一下,新建一个类,然后重新走一边试试
public class AClass
{
    public int x;

    public AClass(int x)
    {
        this.x = x;
    }
}

private void test()
{
    List list = new List();
    list.Add(new AClass(1));
    list.Add(new AClass(2));
    list.Add(new AClass(3));

    Debug.Log("list[0].x = " + list[0].x);
    list[0].x = 4;
    Debug.Log("list[0].x = " + list[0].x);
}

这次通过打印我们可以发现,list[0].x 的值是被改变了的。到这里,我们就需要想想这到底发生了什么。。

我们需要看看Vector3 和我们创建的 AClass 的不同。这时候你就会发现,Vector3 并不是class,而是一个struct。或许你会问这又代表了什么?
我们知道 list[i] 是继承 IList 中的方法
object this[int index] { get; set; }
那么当get的时候 如果是struct,那么它其实就是一个值传递; 如果是class,它传递的是对象的地址。
再通俗一点就是说:值传递 它返回的是一个临时拷贝,而当你改变这个拷贝的时候,对原来的object是不会起到任何作用的,因此编译器认为这是毫无意义的,就从源头上禁止了这种做法。
当然这是作为左值,尝试去改变的时候,如果是右值,只是使用了它的属性值,这还是可以的。
所以,探索到这里,我们就知道了,这其实就是一个值传递和地址传递的区别,这就不足为怪了。

你可能感兴趣的:(Unity,C#)