为什么修饰符 "in" 对数组不起作用?

Why doesn't the modifier "in" work for arrays?

我写了一些代码来检查关键字“in”(C#)。添加我知道“in”意味着该参数将是只读的。但它适用于参数类型为 int、double 等的函数,但不适用于 int[]、double[] 等

所以,我写了这段代码,但我没有在第 arr1[i] += 1; 行看到错误。太奇妙了。有人可以解释一下为什么吗?

static int summArray(in int[] arr1, in int[] arr2, int length) 
{
    int summ = 0;

    if (arr1.Length >= length && arr2.Length >= length) 
    {
        for (int i = 0; i < length; i++)
        {
            arr1[i] += 1;
            summ += arr1[i];
            summ += arr2[i];
        }
        return summ;
    }
    throw new ArgumentException("too small array!");
}

不只是数组;对于任何引用类型, in 修饰符可能会以同样的方式让您大吃一惊。如果不是很明显,数组是引用类型,即使它们是值类型的数组。您可以随时修改数组的内容,就像您可以设置 class Person 实例的 .Name 一样。 in他们的兄弟们只关心给变量引用赋值,而不是改变变量引用的数据内容

I know that "in" means that parameter will be readonly

变量本身是只读的,因为它不能被重新分配以指向其他东西,但这并不意味着变量指向的东西不能被修改

in 是方法参数的三个标记的一部分:inrefout

它们主要用于向其他开发人员指示该方法将如何处理传递的引用:

  • out 表示“该方法肯定会为给定的变量引用分配一些东西”(即不要浪费精力编写将提供具有值的变量的代码,因为它将被替换)
  • ref 表示“该方法可能会将引用的对象替换为另一个”(即注意检查该方法是否会将您精心创建的数据替换为其他数据,并保存您自己对您的数据(如果您不想冒丢失数据的风险)
  • in 意思是“该方法不能用不同的对象替换参数引用的对象”(即无论如何需要 5 分钟的 CPU 时间来制作完美的对象;它将通过引用传递,但是当方法完成时,您的代码不会发现它被交换为其他东西)

in 与完全不指定任何内容略有不同;没有说明符通过创建对调用方法持有的对象的引用的副本来传递。当提供一个复制引用时,被调用的方法可以将该引用指向另一个对象,但这对调用者没有任何影响;被调用方法修改副本,因此调用方法不会对其引用实际引用的内容进行任何更改。对于通过原始引用传递的变量,存在被调用方法将它换成其他东西的风险,这意味着调用者可能会丢失它已经准备好的数据

//out: caller shouldn't supply a value; LongProcess's efforts are wasted

var x = LongProcess();
SomeOutMethod(out x); 


void SomeOutMethod(out object x){
  x = somethingelse; //must be done
}



//ref: caller should be careful if supplying a value; LongProcess's efforts may be wasted

var x = LongProcess();
var savedX = x;        //preserve my X in case...
SomeRefMethod(ref x);  //maybe this will replace x


void SomeRefMethod(ref object x){
  x = somethingelse; //may be done
}



//in: caller shouldn;t worry about supplying a value; LongProcess's efforts won't be wasted

var x = LongProcess();
SomeInMethod(in x); 


void SomeInMethod(in object x){
  x = somethingelse; //cannot be done
}

当然 none 这与修改传递的对象引用的 内容 有任何关系

void ModifyIt(Person p){
  p.Name = "John";         //always possible unless Person forbids it
}

void ModifyIt(int[] x){
  x[0] = 1;                //always possible no matter what
}

in/ref/out 纯粹与 p = new Person...x = new int10] 等操作有关。与 p.Name = ...x[0] = ...

完全无关