tags:

views:

205

answers:

7

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.

+2  A: 

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];
         }
     }
BobbyShaftoe
Common misconception. Objects are not passed by reference. _References_ are passed by value.
Joel Coehoorn
It's probably more accurate to say that for reference types (like object) the reference is passed by value. For value types (like primitives and structs), the value is passed by value.
LBushkin
It helps if you know arrays are all objects (instances of System.Array specifically).
R. Bemrose
You might want to add: even though the integer type is a value type (not passed as reference by default) the Array type IS a reference type and is therefore passed by reference.
Quibblesome
@Joel Coehoom, well I disagree that I have a misconception. I said Objects are passed by references; I did not say references are passed by reference. Perhaps I could have reworded it but I chose to discuss it with respect to objects themselves.
BobbyShaftoe
@Bobby: But objects aren't passed by reference, in fact, objects aren't passed at all. References to objects are passed and by default, they are passed by value.
Chris Dunaway
Daniel Pryden
This should still be corrected though, Joel is correct, and this is a concept that many people get confused. The answer should be correct to avoid this type of confusion, and it is not.
Ed Swangren
Sure, if you stipulate that objects are not passed at all then yes I agree. I suppose the fact that System.ValueType inherits from System.Object makes my wording more confusing than it should be.
BobbyShaftoe
+1  A: 

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.

Joseph
A: 

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).

Will
You are correct that there is a difference between passing a *reference type* by *value* (how arrays are normally passed), and passing a *value type* by *value* (how ints are normally passed), but you are incorrect because it is also possible to pass a reference type **or** a value type *by reference* (using the `ref` keyword), and that is something else altogether.
Daniel Pryden
A: 

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.

http://stackoverflow.com/questions/1293111/what-is-different-between-passing-by-value-and-passing-by-reference-using-c

LBushkin
I thought Arrays are passed by values.
udana
Arrays are reference types not value types. In C# references are passed by value. This means passing an array to another functions will allow that function to potentially make changes that are visible to the caller... or anyone else who has access to that same array reference.
LBushkin
+2  A: 

The array reference is passed by value automatically because it is a reference type.

Read:

Reference Types

Value Types

Philip Wallace
It's not passed by value because it is a reference type, it's passed by value because that is the default passing mechanism.
Chris Dunaway
Interesting...Just out of interest - if that is the case, then why is the ref keyword required for value types? This implies that passing the reference by value is not default.
Philip Wallace
+2  A: 

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.

gWiz
+1 for explaining the difference between passing a value type by reference and passing a reference type by value. I agree, it's easier if you just think of all reference types as being syntactic sugar for pointers. This is similar to the difference between references and pointers in C++, something that many programmers also get confused about.
Daniel Pryden
+3  A: 

There are two concepts here.

  1. Reference types vs. value types
  2. 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".

Lasse V. Karlsen
+1 Good answer. I clarified a couple of the comments in your code samples regarding value types and reference types.
Daniel Pryden
Thanks (for joke) you treated me like a born baby,thanks for taking me 15 years back :( :( Baby is crying .Thanks Lasse for your arduous effort.
udana
Sorry, that was not my intent at all. Please let me know what I can change to rectify that. My point was that your question, for whatever reason, is a common one, and typically born of the confusion I mention. I really did mean the part where I said that I apologize if this is not the case for you.
Lasse V. Karlsen
@udana: Part of the purpose of StackOverflow is not only to answer *your* question, but to provide a repository of knowledge so *someone else* can come here and find the answer as well. To that end, it's useful to have clear, well-written explanations, even if the answers become a bit pedantic. No one is trying to imply anything about *you*, so don't take it personally.
Daniel Pryden
@ Lasse Sorry for the delayed reply.System restarted.Kindly accept my sincere appologies. As My English was not good,you people misunderstood.Actually i tried to convey that even a born baby can understand your explanation.When i tried to add some more line,the system restarted. "If you write a book with similar explanation and examples definitely it will be helpful to for beginners like us".
udana
@Daniel Pryden I completely agree with you,but just i missed out in that comment what i really want to convey.That made that comment as belligerent note.Actually that was not my intention.anyhow thank you for giving this opportunity to express my appologies.
udana