nzscott
nzscott

Reputation: 63

C# Calling a Method, and variable scope

Why is cards being changed below? Got me puzzled.. understand passing by ref which works ok.. but when passing an Array is doesn't do as I expect. Compiling under .NET3.5SP1

Many thanks

void btnCalculate_Click(object sender, EventArgs e)
{
    string[] cards = new string[3];
    cards[0] = "old0";
    cards[1] = "old1";
    cards[2] = "old2";
    int betResult = 5;
    int position = 5;
    clsRules myRules = new clsRules();
    myRules.DealHand(cards, betResult, ref position);  // why is this changing cards!
    for (int i = 0; i < 3; i++)
        textBox1.Text += cards[i] + "\r\n";  // these are all new[i] .. not expected!

    textBox1.Text += "betresult " + betResult.ToString() + "\r\n";  // this is 5 as expected
    textBox1.Text += "position " + position.ToString() + "\r\n"; // this is 6 as expected
}

public class clsRules
{
    public void DealHand(string[] cardsInternal, int betResultInternal, ref int position1Internal)
    {
        cardsInternal[0] = "new0";
        cardsInternal[1] = "new1";
        cardsInternal[2] = "new2";

        betResultInternal = 6;
        position1Internal = 6;
    }
}

Upvotes: 2

Views: 388

Answers (7)

mfeingold
mfeingold

Reputation: 7134

When you are passing an array as an object it is not copied. The receiving method works with the same instance. In a sense arrays are always passed by ref. When an array as well as an instance of any other reference type is passed as a parameter the receiving method gets its own copy of a reference on the same instance of the type. No copy of the actual object is created.

If you need to pass a copy you have to be explicit about this: create a copy yourself or clone the array. The reason it is not done for you is obvious - copying an array can be expensive, you do not want it unless it is really necessary

Upvotes: 1

JaredPar
JaredPar

Reputation: 755587

Arrays are reference types which in short means the value of the array is not directly contained within a variable. Instead the variable refers to the value. Hopefully the following code will explain this a bit better (List<T> is also a reference type).

List<int> first = new List<int>()( new int[] {1,2,3});
List<int> second = first;
first.Clear();
Console.WriteLine(second.Count);  // Prints 0

In this scenario there is a List<int> created on the first line which is referred to by variable first. The second line does not create a new list but instead creates a second variable named second which refers to the same List<int> object as first. This logic applies to all reference types.

When you pass the variable cards into the method you do not pass a copy of the full array but instead a copy of the variable cards. This copy refers to the same array object as the original cards. Hence any modifications you make to the array are visible through the original reference.

Upvotes: 5

Jon Skeet
Jon Skeet

Reputation: 1504022

As other answers have said, it's because a reference is being passed by value.

I have an article on argument passing in C# which you may find useful, in addition to the answers here.

Upvotes: 2

Christian Hayter
Christian Hayter

Reputation: 31071

When passing parameters to methods, there are three different concepts to be aware of:

  • By Value vs By Reference parameters
  • Value vs Reference types
  • Mutable vs Immutable types

In your example, the string array is a Reference type, is a Mutable type, and is passed By Value. The compiler will always let you change the content of the array because it is Mutable. However, since it is a Reference type, the calling code and the called code both point to the same array contents, so the calling code "sees the changes". The fact that it's passed by value in this case is irrelevant, since although the called code's array variable has indeed been passed a copy of the calling code's variable, they both point to the same location in memory.

Upvotes: 2

Fredrik Ullner
Fredrik Ullner

Reputation: 2166

Arrays are reference types, thus are subject to change.

Upvotes: 1

Guffa
Guffa

Reputation: 700910

When you are passing a reference type (like an array) to a method by value, you are passing a copy of it's reference. It's still the same object that is referenced, it doesn't create a copy of the array itself.

Upvotes: 2

rein
rein

Reputation: 33465

A variable of a reference type does not contain its data directly; it contains a reference to its data. When you pass a reference-type parameter by value, it is possible to change the data pointed to by the reference, such as the value of a class member. However, you cannot change the value of the reference itself; that is, you cannot use the same reference to allocate memory for a new class and have it persist outside the block. To do that, pass the parameter using the ref or out keyword.

http://msdn.microsoft.com/en-us/library/s6938f28(VS.80).aspx

Upvotes: 4

Related Questions