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, ... );
Related
I have seen a couple of the example on internet stated that I have to reset the stream by
stream.Seek(0, SeekOrigin.Begin);
However, if I pass the stream into a method as
public static bool ValidateStreamLine(Stream stream)
Do I have to still reset the stream?
Understand that on usual case if I pass in int, string, float or any other general variable type as
public static bool ValidateInt(int i)
the value of int i would not change.
Would that be any difference of the nature of Pass-by Value method on how the method react to stream?
You seem to be misunderstanding how arguments are passed in C#. By default, all arguments are passed by value in C#. In order to pass them by reference you need to use a special keyword: ref or out the latter being normally used when the argument is used as a second output of a given method. (See int.TryPase for example).
The important thing to understand here is that arguments passed by value behave quite diferently if the type of the argument is a reference type or a value type. This is where you seem to be confused.
To understand how it all works, make sure you are clear on the following:
Variables hold values.
The value of a variable whose type is a value type, is the value type's instance itself:
int i = 1 // i holds the value 1
The value of a variable whose type is a reference type is not the instance of said type. The value is the memory address where that instance lives.
string s = "Hello!" // s does not hold "Hello!" it holds a number that points to a place in memory where the string "Hello!" lives.
So, now that we are clear on that, what happens when you pass arguments by value (C#'s default)? What happens is that a copy of the variable is made and the copy is passed to the method.
If the type is a reference type, what is really copied and passed to the method is the value stored in the variable. And what is that? The memory address where the object referenced by the variable lives. So you see what happens? Both the original variable and the copied variable both point to the same object:
public class Foo
{
var frobbed = false;
public bool Frobbed { get { return frobbed; } }
public void Frob() { frobbed = true; }
}
void Frob(Foo foo) { foo.Frob(); }
var myFoo = new Foo();
Frob(myFoo);
Console.WriteLine(myFoo.Frobbed); //Outputs True! Why? Because myFoo and foo both point to the same object! The value of both variables (memory address) is the same!
If the type is a value type, the value itself of the value type is copied and handed to the method so there is no way the method can modify the value type stored in the original variable.
public void Increment(int i) { i = i + 1; }
var myInt = 1;
Increment(myInt);
Console.WriteLine(myInt); //Outputs 1, not 2. Why? i holds its own copy of 1, it knows nothing about the copy of 1 stored in myInt.
Things change when you pass arguments by reference. Now, the argument passed to the method is not a copy, its the original variable itself. A logical question follows; does this actually change anything in how reference types behave? The answer is yes, quite a lot:
public void ByValueCall(string s)
{
s = "Goodbye";
}
public void ByReferenceCall(ref string s)
{
s = "Goodbye";
}
var myString = "Hello!";
Console.WriteLine(ByValueCall(myString )); //outputs "Hello!"
Console.WriteLine(ByValueCall(myString )); //outputs "Goodbye!"
This behavior is identical with value types too. What is happening here?
When you pass an argument by value, the method gets a copy of the variable; therefore assigning a new value to the argument is really just assigning a new value to the copy; the original variable at the callsite doesn't care that you change the value of it's copy, be it a value type or a reference type. It will keep holding the value it always had.
When passing an argument by reference, you are not passing a copy, you are passing the variable itself. In that case assigning a new value to the variable will persist at the callsite. A canonical example is the following swap method:
public void Swap(ref int a, ref int b)
{
var temp = a;
a = b;
b = temp;
}
var i1 = 1;
var i2 = 2;
Swap(ref i1, ref i2);
var b = i1 == 2; //true
b = i2 == 1; //true
So after all of this, you should understand why the following behaves the way it does:
public ResetStream(Stream stream)
{
stream.Seek(0, SeekOrigin.Begin);
}
var myStream = new ...
myStream.Read(bytes, 0, 1024);
ResetStream(myStream);
var isAtOrigin = myStream.Position == 0; //Returns true!
In the example of Microsoft's web there are below codes:
class TestRef
{
static void FillArray(ref int[] arr)
{
// Create the array on demand:
if (arr == null)
{
arr = new int[10];
}
// Fill the array:
arr[0] = 1111;
arr[4] = 5555;
}
}
If I delete the line of if (arr == null), the error output will be 0 0 0 0 0 not 1 2 3 4 5. Why?
This is because you are passing by ref this means that you are changing the pointer for that variable in the main method.
You are assigning it to a new int[] that is filled with the default value of int which is 0
its happening because when you put your code as it is it mean you are passing your intArray to the method but when you remove the lines as you have mentioned in this case new int[] is assigned to variable which will fill default 0 in your array.
this line arr = new int[10]; is assigning new int[] when you remove conditions.
As documented in the official site :-
A ref parameter of an array type may be altered as a result of the
call. For example, the array can be assigned the null value or can be
initialized to a different array.
Here in FillArray function you are passing the array by reference
but when you remove the if block
you re-initialize the array
when you initialize a value type array the elements take default value of the value typeIn this case it is int which have default value 0
You need to understand pass by value vs pass by reference in C#
http://www.programminginterviews.info/2011/05/pass-by-value-versus-reference-in-c.html
also value type vs ref type
http://www.albahari.com/valuevsreftypes.aspx
Why does the original string remain unchanged in example 1 and the original instance not get nulled in example 2, when the string property of an object instance is changed in example 3?
class A { public string property = "class a"; }
static void Main(string[] args)
{
//Example1
string var = "something";
string[] array = new string[] { var };
array[0] += " again";
// var is unchanged, contents in array slot zero are changed
//Example2
A instance = new A();
object[] array2 = new object[] { instance };
array2[0] = null;
// instance is also unchanged, contents in array slot zero are now null
//Example3
A anotherInstance = new A();
object[] array3 = new object[] { anotherInstance };
(array3[0] as A).property = " else";
// the *propery* of anotherInstance changes as expected
return;
}
When you assign a value in an array, you create a copy of the original value. You're not creating a copy of the string itself, but a copy of the value of the "var" variable - which is a string reference. After that point of time, there's no relationship between the variable and the array element - they happen to have the same value immediately afterwards, but they're independent. Changing the array element to make it refer to a different object doesn't change the value of the variable, or vice versa.
In particular, this line:
array[0] += " again";
does not change the contents of the existing string. Instead, it creates a new string and assigns that reference to array[0].
Now in your "Example3" you aren't changing the value of the array element itself - you're changing the contents of the object that both anotherInstance and array3[0] refer to. It's like two people knowing about the same house - if one person paints the door red, the other person will see the red door too.
This all has very little to do with arrays - you'd see the same effects with individual variables too. See my article on reference and value types for further information.
String in .NET are immutable. This means that once they are created/initialized they cannot be changed subsequently. When you do appending to a string a new string is created as opposed to the string being destroyed and reassigned again.
In your first example the first element of the array is a reference to a string. You then create a new string with + and change the first element of the array to be a reference to that new string. var is still a reference to the old string as you did not change var.
In your second example the first element of the array is a reference to an instance of A and again you just change the reference, not the referred-to object.
In your third example, you don't change the reference (you don't reassign array3[0], i.e. you never do array3[0] = something), but you actually change the object that is being referred to. This change also affect anotherInstance because both anotherInstance and array[0] are references to the same object.
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).
I'm not a veteran in socket programming, so while analyzing code I found in a database API I came across this code
public static void WriteInt(int i, NetworkStream bufOutputStream)
{
byte[] buffer = new byte[IntSize];
WriteInt(i, buffer, 0);
bufOutputStream.Write(buffer, 0, buffer.Length);
}
public static void WriteInt(int i, byte[] byte_array, int pos)
{
byte_array[pos] =(byte)( 0xff & (i >> 24)); byte_array[pos+1] = (byte)(0xff & (i >> 16)); byte_array[pos+2] = (byte)(0xff & (i >> 8)); byte_array[pos+3] = (byte)(0xff & i);
}
I understand the bit-shifts what I don't understand is how the 'buffer' var keeps getting a value when no ref is in the args or no return is made. the bitshifts are somehow editing the actual value of buffer?
Your confusion is a very common one. The essential point is realising that "reference types" and "passing by refrence" (ref keyboard) are totally independent. In this specific case, since byte[] is a reference type (as are all arrays), it means the object is not copied when you pass it around, hence you are always referring to the same object.
I strongly recommend that you read Jon Skeet's excellent article on Parameter passing in C#, and all should become clear...
Because an array isn't a value type, it's a reference type. The reference to the location on the heap is passed by value.
I think some examples can show you differences between reference types and value types and between passing by reference and passing by value:
//Reference type
class Foo {
public int I { get; set; }
}
//Value type
struct Boo {
//I know, that mutable structures are evil, but it only an example
public int I { get; set; }
}
class Program
{
//Passing reference type by value
//We can change reference object (Foo::I can changed),
//but not reference itself (f must be the same reference
//to the same object)
static void ClassByValue1(Foo f) {
//
f.I++;
}
//Passing reference type by value
//Here I try to change reference itself,
//but it doesn't work!
static void ClassByValue2(Foo f) {
//But we can't change the reference itself
f = new Foo { I = f.I + 1 };
}
//Passing reference typ by reference
//Here we can change Foo object
//and reference itself (f may reference to another object)
static void ClassByReference(ref Foo f) {
f = new Foo { I = -1 };
}
//Passing value type by value
//We can't change Boo object
static void StructByValue(Boo b) {
b.I++;
}
//Passing value tye by reference
//We can change Boo object
static void StructByReference(ref Boo b) {
b.I++;
}
static void Main(string[] args)
{
Foo f = new Foo { I = 1 };
//Reference object passed by value.
//We can change reference object itself, but we can't change reference
ClassByValue1(f);
Debug.Assert(f.I == 2);
ClassByValue2(f);
//"f" still referenced to the same object!
Debug.Assert(f.I == 2);
ClassByReference(ref f);
//Now "f" referenced to newly created object.
//Passing by references allow change referenced itself,
//not only referenced object
Debug.Assert(f.I == -1);
Boo b = new Boo { I = 1 };
StructByValue(b);
//Value type passes by value "b" can't changed!
Debug.Assert(b.I == 1);
StructByReference(ref b);
//Value type passed by referenced.
//We can change value type object!
Debug.Assert(b.I == 2);
Console.ReadKey();
}
}
The best way to think about this is to think about the variables. Variables are by definition storage locations. What are the storage locations in your program? They are:
the formal parameters i and bufOutputStream of the first WriteInt.
the local variable buffer in the first WriteInt
the elements ("IntSize" of them) of the array referred to by buffer, after it is allocated.
the formal parameters i, byte_array and pos of the second WriteInt
The byte_array storage location and the buffer storage location are different storage locations. But the byte_array storage location contains a reference to the same array that the buffer storage location refers to. Therefore buffer[0] and byte_array[0] refer to the same storage location.
Just think about the storage locations, and it'll all make sense.
C# is like Java in that reference type variables are actually pointers. You always pass by value, but with reference types the value is the location of the object, rather than the object itself. The ref keyword on a reference type is passing the pointer by reference, so an assignment to a ref parameter will change what object the argument passed in points to.
Arrays in .Net are reference types.
Therefore, your function receives a reference to the array object by value. Since there is still only a single array instance, the function can modify the instance and the changes will be seen the caller.
Adding the ref keyword would make the function receive a reference to the array object by reference, and would therefore allow the function to change the reference to refer to a different array instance.
In other words, the ref keyword would allow you to write the following:
public static void WriteInt(int i, ref byte[] byte_array, int pos)
{
byte_array = new byte[0]; //In the caller, the array will now be empty.
}
To demonstrate:
void SetReference(ref byte[] arrayRef) { arrayRef = new byte[1]; }
void SetValue(byte[] arrayVal) { arrayVal[1] = 42; }
byte[] array = new byte[4];
byte[] sameArray = array; //sameArray refers to the same instance
sameArray[0] = 77; //Since it's the same instance, array[4] is also 77.
SetValue(array); //array[1] is 42.
//Since it refers to the same array, sameArray[1] is also 42.
SetReference(ref array); //sameArray now refers to a new array of length 1.
//array still refers to the original array.
byte_array is a reference type.
Like Yuriy Faktorovich said, value types (like int, char, bool ecc.) are passed by default by value (unless you specify ref)
all other types (arrays, and Objects) are passed by default by reference
in your example if u change the values inside the array it will reflect changes also outside the method but you cannot reassign the object.
a full reference about it is in MSDN