C# - 元组数组是可变的,但元组列表不是。我该如何解决这个问题?

bob*_*boy 2 arrays tuples list c#-7.0

我有一个要修改的值对数组。我还需要从这个数组中添加和删除值,所以我使用了一个列表。当我尝试使用列表时,我遇到了错误。

Error CS1612 - Cannot modify the return value of 'List<(int, float)>.this[int]' because it is not a variable

所以我决定去调查一下。我尝试使用数组代替,它......工作正常吗?以下代码仅在 上引发错误arr1[0].Item1 += 1;

static void Main()
    {
        List<(int, float)> arr1 = new List<(int, float)>() { (0, 0) };
        (int, float)[] arr2 = new (int, float)[1];

        arr1[0].Item1 += 1; // This line
        arr2[0].Item1 += 1;
    }
Run Code Online (Sandbox Code Playgroud)

为什么元组数组是可变的,而列表不是?这是因为数组是您可以轻松修改的简单数据块,但列表背后有很多使事情复杂化的后端吗?有没有一种简单的方法可以解决这个问题,还是我必须创建自己的自定义类?

Jon*_*eet 5

为什么元组数组是可变的,而列表不是?

列表本身是可变的,但与您的操作方式不同。请注意,这不是元组特有的任何内容 - 它只是任何可变结构的情况。

列表索引器 getter 返回一个(即在您的情况下元组的副本) - 因此修改该值不会修改列表中的副本。编译器试图避免您对即将被丢弃的值进行更改。数组访问不这样做 -arr2[0]指的是数组中的变量。(数组实际上是变量的集合。)

如果你想改变列表,你必须获取元组,改变它,然后把它放回去:

var tuple = arr1[0];
tuple.Item1++;
arr1[0] = tuple;
Run Code Online (Sandbox Code Playgroud)

请注意,这也解释了为什么不能使用列表访问表达式作为参数的ref参数,但可以对数组执行等效操作:

public void Method(ref int x) => x++;

public void CallMethod()
{
    var list = new List<int> { 0 };
    var array = new int[] { 0 };
    Method(ref list[0]); // Error
    Method(ref array[0]); // Valid
}
Run Code Online (Sandbox Code Playgroud)