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] = ...