How did the code achieve pass by reference? - c#

Inside main i declared a local int[] array (int[] nums). I did not pass it by reference.
But when i print values of local array i get squared value of each element.
What is the reason for that?
delegate void tsquare(int[] a);
static void Main()
{
int[] nums = { 1, 2, 3 };
tsquare sqr = new tsquare(SomeClass.Square);
sqr(nums);
foreach (int intvals in nums)
{
Console.WriteLine(intvals);
}
}
class SomeClass
{
public static void Square(int[] array)
{
for (int i = 0; i < array.Length; i++)
{
array[i] = array[i] * array[i];
}
}
}
Update:
My appologies to all.What i tought is int[] {Array}is a value type,and the Delegate done
some trick on it.Now from your answer ,i understand Array is Reference type.

There are two concepts here.
Reference types vs. value types
Passing by value vs. passing by reference
Let's tackle the second one first.
Passing something by value means that you give the method its own copy of that value, and it's free to change that value however it wants to, without those changes leaking back into the code that called the method.
For instance, this:
Int32 x = 10;
SomeMethod(x); // pass by value
There's no way x is going to be anything other than 10 after the call returns in this case, since whatever SomeMethod did to its copy of the value, it only did to its own value.
However, passing by reference means that we don't really give the method its own value to play with, rather we give it the location in memory where our own value is located, and thus anything that method does to the value will be reflected back to our code, because in reality, there's only one value in play.
So this:
Int32 x = 10;
SomeMethod(ref x); // pass by reference
In this case, x might hold a different value after SomeMethod returns than it did before it was called.
So that's passing by value vs. passing by reference.
And now to muddle the waters. There's another concept, reference types vs. value types, which many confuses. Your question alludes to you being confused about the issue as well, my apologies if you're not.
A reference type is actually a two-part thing. It's a reference, and it's whatever the reference refers to. Think of a house you know the address of. You writing the address on a piece of paper does not actually put the entire house on that paper, rather you have a "reference" to that particular house on your piece of paper.
A reference type in .NET is the same thing. Somewhere in memory there is an object, which is a set of values, grouped together. The address of this object you store in a variable. This variable is declared to be a type which is a reference type, which allows this two-part deal.
The nice thing about reference types is that you might have many references to the same actual object, so even if you copy the reference around, you still only have one object in memory.
Edit: In respect to the question, an array is a reference type. This means that your variable only holds the address of the actual array, and that array object is located somewhere else in memory.
A value type, however, is one thing, the entire value is part of the "value type", and when you make copies of that, you make distinct copies
Here's an example of value types:
struct SomeType
{
public Int32 Value;
}
SomeType x = new SomeType;
x.Value = 10;
SomeType y = x; // value type, so y is now a copy of x
y.Value = 20; // x.Value is still 10
However, with a reference type, you're not making a copy of the object it refers to, only the reference to it. Think of it like copying the address of that house onto a second piece of paper. You still only have one house.
So, by simply changing the type of SomeType to be a reference type (changing struct to class):
class SomeType
{
public Int32 Value;
}
SomeType x = new SomeType;
x.Value = 10;
SomeType y = x; // reference type, so y now refers to the same object x refers to
y.Value = 20; // now x.Value is also 20, since x and y refer to the same object
And now for the final thing; passing a reference type by value.
Take this method:
public void Test(SomeType t)
{
t.Value = 25;
}
Given our class-version of SomeType above, what we have here is a method that takes a reference type parameter, but it takes it as being passed by value.
What that means is that Test cannot change t to refer to another object altogether, and make that change leak back into the calling code. Think of this as calling a friend, and giving him the address you have on your piece of paper. No matter what your friend is doing to that house, the address you have on your paper won't change.
But, that method is free to modify the contents of the object being referred to. In that house/friend scenario, your friend is free to go and visit that house, and rearrange the furniture. Since there is only one house in play, if you go to that house after he has rearranged it, you'll see his changes.
If you change the method to pass the reference type by reference, not only is that method free to rearrange the contents of the object being referred to, but the method is also free to replace the object with an altogether new object, and have that change reflect back into the calling code. Basically, your friend can tell you back "From now on, use this new address I'll read to you instead of the old one, and forget the old one altogether".

The array reference is passed by value automatically because it is a reference type.
Read:
Reference Types
Value Types

Most of the other answers are correct but I believe the terminology is confusing and warrants explanation. By default, you can say that all parameters in C# are passed by value, meaning the contents of the variable are copied to the method variable. This is intuitive with variables of value types, but the trick is in remembering that variables that are reference types (including arrays) are actually pointers. The memory location the pointer contains is copied to the method when it is passed in.
When you apply the ref modifier, the method gets the actual variable from the caller. For the most part the behavior is the same, but consider the following:
public void DoesNothing(int[] nums)
{
nums = new []{1, 2, 3, 4};
}
In DoesNothing, we instantiate a new int array and assign it to nums. When the method exits, the assignment is not seen by the caller, because the method was manipulating a copy of the reference (pointer) that was passed in.
public void DoesSomething(ref int[] nums)
{
nums = new []{1, 2, 3, 4};
}
With the ref keyword, the method can essentially reach out and affect the original variable itself from the caller.
To achieve what you seemed to originally want, you could create a new array and return it, or use Array.CopyTo() in the caller.

In C#, all parameters are passed by value by default. There are two kinds of types in C#, namely value and reference types.
A variable of reference type when passed as a parameter to a function will still be passed by value; that is if the function changes the object referred to by that variable, after the function completes the variable that was passed in will still refer to the same object (including null) as it did prior to calling the function in the same context.
However, if you use the ref modifier when declaring the function parameter than the function may change the object being referenced by the variable in the caller's context.
For Value types this is more straightforward but it is the same concept. Bear in mind, int[] is a reference type (as are all arrays).
Consider the differences in these functions when passing in some some array of ints:
public static void Square1(int[] array)
{
for (int i = 0; i < array.Length; i++)
{
array[i] = array[i] * array[i];
}
}
public static void Square2(int[] array)
{
array = {10, 20, 30};
for (int i = 0; i < array.Length; i++)
{
array[i] = array[i] * array[i];
}
}
public static void Square3(ref int[] array)
{
array = {10, 20, 30};
for (int i = 0; i < array.Length; i++)
{
array[i] = array[i] * array[i];
}
}

You're not passing it by reference. The array is being passed in by value, but arrays in .NET are reference types, so you're passing in a reference to the array, which is why you're seeing the values squared.

Read the following SO question - it explains the differences between pass-by-value and pass-by-reference. The accepted answer has a link in it to a good article about the topic that should help you understand the difference.
what is different between Passing by value and Passing by reference using C#

Arrays are objects and are passed by reference. Ints are structs and are passed by value (unless you use the ref keyword in your method signature as per the picky guy in the comments) (who was right) (but picky).

Related

C# Primitive Types Vs Objects, Passing To Fuction [duplicate]

This question already has answers here:
What is the difference between a reference type and value type in c#?
(15 answers)
Closed 1 year ago.
When I passed my object to a function in c# and change its values, the originals instance values are changed? I have been looking into why this happens but no one is explaining.
class Program
{
static void Main(string[] args)
{
Class1 obj = new Class1();
obj.x = 10;
test(obj);
Console.WriteLine(obj.x); // prints 200
}
static void test(Class1 a)
{
a.x = 200;
}
}
When I tried this with the int data type, it did not change.
I have a deep understand of pass my value and reference. But in c#, I am quite confused on what is going on?
I want to know why c# changes original obj function value. It should still print 10.
When you tried it with int, a copy of the int variable was passed. For the time you ran the method your memory contained two ints, you modified one which was then thrown away
Had you passed the int with ref the original int would have been passed and the method would have modified the original value
When you pass objects, a reference to the object is passed and whether you use ref or not you can modify properties of the object and the calling method will see those modifications. The difference with using ref or not on an object is that with ref you can swap the object for a whole new one (with new) keyword and the original method will get the new object. Without ref, the original method will retain the original object because the reference that was passed (and subsequently changed for a new object) was a copy
Forget calling a method for a moment, let's do it simpler:
int x = 0;
int y = x;
y++;
What value do you now expect x to have?
It has 0; y is a copy of the value x has
Person p = new Person(){ Name = "John" };
Person q = p;
q.Name = "Mary";
What name do you expect p now to have? (It's Mary)
This is like what is happening with your posted code, so you already understand it in the context of not calling a method - y is a copy of x (and they refer to different data in memory, changing one does not change the other), q is a copy of a reference to p (but they both refer to the same data in memory, changing the data means both references see the change)

Why does assignment to parameter not change object?

classes deal with the reference types and traditional data types deal with the value type just for example :
int i=5;
int j=i;
i=3 ; //then this will output i=3 and j=5 because they are in the different memory blocks .
Similarly if we talk about the object of a class say point class
class point
{
public int x,y;
void somefucnt(point p,int x)
{
Console.writeline("value of x is "+p.x);
x=22;
Console.writeline("value of x is "+p.x);
}
}
class someotherclass
{
static void Main(string [] args )
{
p1.x=10;
p1.somefunct(p1,p1.x);
}
}
Both console.write statements are printing 10 , despite ive changed x to some other value ? why is it so ?since p is just the reference to x so it should be updated by changing values of x . this thing is really confusing me alot .
The observed behavior has nothing to do with Value types vs Reference types - it has to do with the Evaluation of Strategy (or "calling conventions") when invoking a method.
Without ref/out, C# is always Call by Value1, which means re-assignments to parameters do not affect the caller bindings. As such, the re-assignment to the x parameter is independent of the argument value (or source of such value) - it doesn't matter if it's a Value type or a Reference type.
See Reference type still needs pass by ref? (on why caller does not see parameter re-assignment):
Everything is passed by value in C#. However, when you pass a reference type, the reference itself is being passed by value, i.e., a copy of the original reference is passed. So, you can change the state of object that the reference copy points to, but if you assign a new value to the reference [parameter] you are only changing what the [local variable] copy points to, not the original reference [in the argument expression].
And Passing reference type in C# (on why ref is not needed to mutate Reference types)
I.e. the address of the object is passed by value, but the address to the object and the object is the same. So when you call your method, the VM copies the reference; you're just changing a copy.
1 For references types, the phrasing "Call By Value [of the Reference]" or "Call by [Reference] Value" may help clear up the issue. Eric Lippert has written a popular article The Truth about Value Types which encourages treating reference values as a distinct concept from References (or instances of Reference types).
void somefucnt(point p,int x){
Console.writeline("value of x is "+p.x);
x=22;
Console.writeline("value of x is "+p.x);
}
Here, the x=22 won´t change p.x but the parameter x of (point p,int x)
Normally, your assumtion about values/references is ok (if I understood it correctly).
Tip: Google for c# this instead of passing a object to it´s own method
You change the value of the parameter (x), not the value of p.x, value types are passed by value unless you use the ref keyword.
Like in your first example, there is no relationship between i and j as well as the parameter x, and p1.x.Each variable has it's own space in the memory.So changing one of them doesn't affect to the other.
You have two different variables named x in the somefucnt function. One is the member variable x which you are trying to change, the other is the function input parameter in void somefucnt(point p, int x). When you say x = 22, the input parameter x is changed instead of the member variable x.
If you change the line x = 22 to this.x = 22 then it should work as you expect.
Side note:
A good practice to avoid confusion is to always have class members private and name them as _x. Otherwise, have public auto properties in CamelCase, like this:
public int X { get; set; }
These methods avoid ambiguity between class variables and function input variables.

Difference between Reference Types and References

I am reading following blog by Eric Lippert: The truth about Value types
In this, he mentions there are 3 kinds of values in the opening:
Instance of Value types
Instance of Reference types
References
It is incomplete. What about references? References are neither value types nor instances of reference types, but they are values..
So, in the following example:
int i = 10;
string s = "Hello"
First is instance of value type and second is instance of reference type. So, what is the third type, References and how do we obtain that?
So, what is the third type, References and how do we obtain that?
The variable s is a variable which holds the value of the reference. This value is a reference to a string (with a value of "Hello") in memory.
To make this more clear, say you have:
string s1 = "Hello";
string s2 = s1;
In this case, s1 and s2 are both variables that are each a reference to the same reference type instance (the string). There is only a single actual string instance (the reference type) involved here, but there are two references to that instance.
Fields and variables of reference type, such as your s, are references to an instance of a reference type that lives on the heap.
You never use an instance of a reference type directly; instead, you use it through a reference.
A reference is not really a 'third type'. It's actually a pointer that refers to a concrete instance of an object. Take a look at this example:
class MyClass
{
public string Str { get; set; }
}
class Program
{
static void Main(string[] args)
{
int a = 1;
int b = 2;
int c = 3;
var myObj = new MyClass
{
Str = "Whatever"
};
Console.WriteLine("{0};\t{1};\t{2};\t{3}", a, b, c, myObj.Str);
MyFunction(a, ref b, out c, myObj);
Console.WriteLine("{0};\t{1};\t{2};\t{3}", a, b, c, myObj.Str);
Console.ReadLine();
}
static void MyFunction(int justValue, ref int refInt, out int outInt, MyClass obj)
{
obj.Str = "Hello";
justValue = 101;
refInt = 102;
outInt = 103; // similar to refInt, but you MUST set the value of the parameter if it's uses 'out' keyword
}
}
The output of this program is:
1; 2; 3; Whatever
1; 102; 103; Hello
Focus on the MyFunction:
The first parameter we pass is a simple int which is a value type. By default value types are cloned when passed as the parameter (a new instance is being created). That's why the value of 'a' didn't change.
You can change this behavior by adding 'ref' or 'out' keyword to the parameter. In this case you actually pass a reference to that very instance of your int. In MyFunction the value of that instance is being overridden.
Here you can read move out ref and out
The last example is the object of MyClass. All classes are reference types and that's why you always pass them as references (no special keywords needed).
You can think about a reference as about an address in computer memory. Bytes at that address compose your object. If you pass it as value, you take that bytes out and pass them to a function. If you pass it as a reference you only pass the address. Than in your called function you can read bytes from that address or write to that address. Every change affects the calling function variables, because they point to exactly the same bytes in computer memory. It's not exactly what happens in .Net (it runs in a virtual machine), but I think this analogy will help you understand the concept.
Why do we use references? There are many reasons. One of them is that passing a big object by value would be very slow and would require cloning it. When you pass a reference to an object, than no matter how big that object is you only pass w few bytes that contain it's 'address' in memory.
Moreover your object may contain elements that cannot be cloned (like an open socket). Using reference you can easily pass such an object between functions.
It's also worth mentioning that sctructs, even though they look very similar to classes are actually value types and behave as value types (when you pass a struct to a function, you actually pass a clone - a new instance).

Storing an object by reference or workarounds

I am building internal logic for a game in C# and coming from C++ this is something that might be lost in translation for me.
I have an object, Ability that calculates the bonus it provides and returns that as an integer value. The calculation is meant to be dynamic and can change depending on a variety of variables.
public class Ability: Buffable
{
public string abbr { get; private set; }
public Ability(string name, string abbr, uint score) : base(name, score)
{
this.abbr = abbr;
}
// Ability Modifier
// returns the ability modifier for the class.
public int Ability_modifier()
{
const double ARBITARY_MINUS_TEN = -10;
const double HALVE = 2;
double value = (double)this.Evaluate();
double result = (value + ARBITARY_MINUS_TEN) / HALVE;
// Round down in case of odd negative modifier
if (result < 0 && ((value % 2) != 0))
{
result--;
}
return (int)result;
}
I then have another object, Skill which should be aware of that bonus and add it into it's calculation. I wanted to pass an Ability into the constructor of Skill by reference and then store that reference so that if the Ability changed the calculation would as well. The obvious problem with this being that apparently storing references is taboo in C#.
Is there either a work around way to do this or an alternate way to approach this problem that my pointer infested mind isn't considering? I would greatly prefer not to have to pass the ability to the function that evaluates Skill every time, since the one referenced never changes after construction.
The obvious problem with this being that apparently storing references is taboo in C#.
Absolutely not. References are stored all over the place. You're doing it here, for example:
this.abbr = abbr;
System.String is a class, and therefore a reference type. And so the value of abbr is a reference.
I strongly suspect you've misunderstood how reference types work in C#. If you remember a reference to an object, then changes to the object will be visible via the reference. However, changes to the original expression you copied won't be.
For example, using StringBuilder as a handy mutable reference type:
StringBuilder x = new StringBuilder("abc");
// Copy the reference...
StringBuilder y = x;
// This changes data within the object that x's value refers to
x.Append("def");
// This changes the value of x to refer to a different StringBuilder
x = new StringBuilder("ghi");
Console.WriteLine(y); // abcdef
See my articles on references and values, and parameter passing in C# for much more detail.
I am not quite seing enough of your code to give a concrete example, but the way to do this is to pass in a lambda delegate such as () => object.property instead of this: object.property.
In C#, there are reference types and value types. All non-value-type objects are passed by reference, so there should be no issue with references. Just pass it, and it will be passed by reference.

Passing Arrays by Value and by Reference

These are example from a c# book that I am reading just having a little trouble grasping what this example is actually doing would like an explanation to help me further understand what is happening here.
//creates and initialzes firstArray
int[] firstArray = { 1, 2, 3 };
//Copy the reference in variable firstArray and assign it to firstarraycopy
int[] firstArrayCopy = firstArray;
Console.WriteLine("Test passing firstArray reference by value");
Console.Write("\nContents of firstArray " +
"Before calling FirstDouble:\n\t");
//display contents of firstArray with forloop using counter
for (int i = 0; i < firstArray.Length; i++)
Console.Write("{0} ", firstArray[i]);
//pass variable firstArray by value to FirstDouble
FirstDouble(firstArray);
Console.Write("\n\nContents of firstArray after " +
"calling FirstDouble\n\t");
//display contents of firstArray
for (int i = 0; i < firstArray.Length; i++)
Console.Write("{0} ", firstArray[i]);
// test whether reference was changed by FirstDouble
if (firstArray == firstArrayCopy)
Console.WriteLine(
"\n\nThe references refer to the same array");
else
Console.WriteLine(
"\n\nThe references refer to different arrays");
//method firstdouble with a parameter array
public static void FirstDouble(int[] array)
{
//double each elements value
for (int i = 0; i < array.Length; i++)
array[i] *= 2;
//create new object and assign its reference to array
array = new int[] { 11, 12, 13 };
Basically there is the code what I would like to know is that the book is saying if the array is passed by value than the original caller does not get modified by the method(from what i understand). So towards the end of method FirstDouble they try and assign local variable array to a new set of elements which fails and the new values of the original caller when displayed are 2,4,6.
Now my confusion is how did the for loop in method FirstDouble modify the original caller firstArray to 2,4,6 if it was passed by value. I thought the value should remain 1,2,3.
Thanks in advance
The key to understanding this is to know the difference between a value type and a reference type.
For example, consider a typical value type, int.
int a = 1;
int b = a;
a++;
After this code has executed, a has the value 2, and b has the value 1. Because int is a value type, b = a takes a copy of the value of a.
Now consider a class:
MyClass a = new MyClass();
a.MyProperty = 1;
MyClass b = a;
a.MyProperty = 2;
Because classes are reference types, b = a merely assigns the reference rather than the value. So b and a both refer to the same object. Hence, after a.MyProperty = 2 executes, b.MyProperty == 2 since a and b refer to the same object.
Considering the code in your question, an array is a reference type and so for this function:
public static void FirstDouble(int[] array)
the variable array is actually a reference, because int[] is a reference type. So array is a reference that is passed by value.
Thus, modifications made to array inside the function are actually applied to the int[] object to which array refers. And so those modifications are visible to all references that refer to that same object. And that includes the reference that the caller holds.
Now, if we look at the implementation of this function:
public static void FirstDouble(int[] array)
{
//double each elements value
for (int i = 0; i < array.Length; i++)
array[i] *= 2;
//create new object and assign its reference to array
array = new int[] { 11, 12, 13 };
}
there is one further complication. The for loop simply doubles each element of the int[] that is passed to the function. That's the modification that the caller sees. The second part is the assignment of a new int[] object to the local variable array. This is not visible to the caller because all it does is to change the target of the reference array. And since the reference array is passed by value, the caller does not see that new object.
If the function had been declared like this:
public static void FirstDouble(ref int[] array)
then the reference array would have been passed by reference and the caller would see the newly created object { 11, 12, 13 } when the function returned.
What a confusing use of terms!
To clarify,
for a method foo(int[] myArray), "passing a reference (object) by value" actually means "passing a copy of the object's address (reference)". The value of this 'copy', ie. myArray, is initially the Address (reference) of the original object, meaning it points to the original object. Hence, any change to the content pointed to by myArray will affect the content of the original object.
However, since the 'value' of myArray itself is a copy, any change to this 'value' will not affect the original object nor its contents.
for a method foo(ref int[] refArray), "passing a reference (object) by reference" means "passing the object's address (reference) itself (not a copy)". That means refArray is actually the original address of the object itself, not a copy. Hence, any change to the 'value' of refArray, or the content pointed to by refArray is a direct change on the original object itself.
All method parameters are passed by value unless you specifically see ref or out.
Arrays are reference types. This means that you're passing a reference by value.
The reference itself is only changed when you assign a new array to it, which is why those assignments aren't reflected in the caller. When you de-reference the object (the array here) and modify the underlying value you aren't changing the variable, just what it points to. This change will be "seen" by the caller as well, even though the variable (i.e. what it points to) remains constant.
idea for you all there with knowledge of .net open sources to implement the logics;
//Sample Code, Illustration;
Method1(params dynamic[] var1) {
var1[0]=new dynamic[3] { 1,2,3 }
}
the var1 is not specified or cannot be ref ?
a usage scenario would be ...
//Sample Code, Illustration;
dynamic[] test = new dynamic[];
Method1( ref test,x,x,x,x );
System.Windows.MessageBox.Show( test[2].ToString() );
to indicate ref only when, not being a parameter specific;
and a ref to array items;
//result is IndexOutOfBounds;
this is only a illustrationm it can be done by returning a array and use like:
test = Method1( test,... );
instead of :
Method1( ref test,x,x,..., ref test[x], ref test2, ... );

Categories

Resources