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

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

2013年01月27日 14:18:05 苏内容
  标签: List
阅读:7328

无法修改“System.Collections.Generic.List<SueseGeometry.Vector3>.this[int]”的返回值,因为它不是变量


使用List写代码的时候遇到了一个“怪异”的现象,无法修改List中对象的属性值。

下面就具体使用代码一起来看一下:

private void test()

{

    List<Vector3> list = new List<Vector3>();

    list.Add(new Vector3(1, 0, 0));

    list.Add(new Vector3(2, 0, 0));

    list.Add(new Vector3(3, 0, 0));

 

    // 使用下面这句代码的时候就会出现编译错误

    // 错误提示如下

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

    list[0].x = 4f;

}

这个就让人比较纳闷了,然后我们尝试使用一下Vector3中的Set方法

private void test()

{

    List<Vector3> list = new List<Vector3>();

    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<AClass> list = new List<AClass>();

    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是不会起到任何作用的,因此编译器认为这是毫无意义的,就从源头上禁止了这种做法。

当然这是作为左值,尝试去改变的时候,如果是右值,只是使用了它的属性值,这还是可以的。

所以,探索到这里,我们就知道了,这其实就是一个值传递和地址传递的区别,这就不足为怪了。


扩展阅读