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

Time:02-15

I wrote some code to check the keyword "in" (C#). Add I know that "in" means that parameter will be readonly. But it works for functions with parameters type int, double, etc, but not for int[], double[], etc.

So, I write this code, and I didn't see Error on line arr1[i] = 1;. It's amazing. Can someone please explain why?

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!");
}

CodePudding user response:

It's not just arrays; the in modifier will possibly surprise you in the same way for any reference type. In case it wasn't immediately obvious, arrays are reference types even if they're an array of value types. You can always modify the contents of an array, just like you can set the .Name of an instance of class Person. in and their brethren are only concerned with assigning to the variable reference, not changing the contents of the data referred to by the variable

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

The variable itself is readonly in the sense that it cannot be reassigned to point to something else, but it doesn't mean that the thing pointed to by the variable cannot be modified

in is part of a trio of markers for arguments to methods: in, ref, out

They are essentially used to indicate to other developers wha tthe method will do with the reference passed:

  • out means "the method will definitely assign something to the given variable reference" (i.e. do not waste effort writing code that will supply a variable having a value because it will be replaced)
  • ref means "the method may replace the object referred to, with another" (i.e. take care to check whether the method will replace your carefully created data with some other data, and save your own reference to your data if you don't want to risk losing it)
  • in means "the method cannot replace the object referred to by the parameter, with a different object" (i.e. by all means take 5 minutes of CPU time to craft the perfect object; it will be passed by reference but your code won't find it swapped for something else when the method is done)

in is slightly different to not specifying anything at all; no specifier passes by creating a copy of the reference to the object held by the calling method. When a copy reference is supplied, the called method may point that reference to another object, but it doesn't make any difference to the caller; the called method modifies a copy so the calling method doesn't experience any change in what its reference actually refers to. For variables passed by original reference there was a risk that the called method would swap it out for something else, meaning the caller could lose data it had prepared

//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
}

And of course none of this has any bearing on modifying the contents of a passed object reference

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 purely relate to operations like p = new Person..., x = new int10]. The have absolutely nothing to do with p.Name = ... or x[0] = ...

  • Related