4

Is it normal that 'user1' and 'user2' point to the same reference in the example below?

I know that I am passing the same variable 'notUsed' to both parameters, but it's not yet instanced so it does't contain a reference to anything. I was quite shocked to see that user1 and user2 are linked to each other.

static void CheckPasswords(out string user1, out string user2)
{
    user1 = "A";
    user2 = "B";

    Console.WriteLine("user1: " + user1);
    Console.WriteLine("user2: " + user2);
}

public static void Main()
{
    string notUsed;
    CheckPasswords(out notUsed, out notUsed);
}

Console shows:

user1: B
user2: B
17
  • 4
    What do you mean? How do you know they're linked? Commented Aug 28, 2017 at 16:15
  • 3
    You're shocked? I fail to see what you would have expected as a result. One variable notUsed having two values? Commented Aug 28, 2017 at 16:17
  • 1
    What are you expecting the output and value of notUsed to be and why? Commented Aug 28, 2017 at 16:17
  • 2
    Of course it's "not yet instanced" -- it's an out variable, those are never instanced before you're calling the method. Nevertheless, it's the same variable referenced twice, not two local variables that are "copied out" at the end of the method. Commented Aug 28, 2017 at 16:18
  • 2
    @John: at user1 = "A". Since user1 points to notUsed, the reference to "A" ends up in notUsed. (And then, of course, it is overwritten by the second statement, since user2 also points to notUsed.) The storage needed for notUsed already exists, even if its contents does not at method entry (or more accurately, the contents are indeterminate/inaccessible). Commented Aug 28, 2017 at 16:26

3 Answers 3

10

When you use the out keyword, you pass by reference. (https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/out-parameter-modifier) Since you are passing by reference, your user1 and user2 are both pointing to the same variable. Hence, when you update one, it updates the other.

Sign up to request clarification or add additional context in comments.

Comments

3

You are passing the variable in by reference. Also, the order of assignments in the method is significant - as written here the variable will contain "B" at the end. If you reverse them, then "A" will be produced.

Compare:

user1 = "A"; // notused now contains "A"
user2 = "B"; // notused now contains "B"
// method ends with the variable notused containing "B"

Versus:

user2 = "B"; // notused now contains "B"
user1 = "A"; // notused now contains "A"
// method ends with the variable notused containing "A"

Comments

1

This:

CheckPasswords(out notUsed, out notUsed);

does not pass the contents of notUsed to the method (as would happen in a method that didn't use out parameters), it passes a reference to notUsed to the method. The same reference twice, in fact. As you say, at this point notUsed does not contain a reference itself yet, but that doesn't matter -- we are not doing anything with the contents, in fact, we don't care since we're passing it as out. Then this:

user1 = "A";

does something special because user1 is not a string parameter -- it's an out string parameter. Rather than assign a value to some local user1, it assigns a value to what user1 is pointing to -- in this case, notUsed. At this point, notUsed holds a reference to "A". And then this:

user2 = "B";

does the same thing, but through the other parameter -- it assigns a reference to "B" to notUsed. And then these two lines:

Console.WriteLine("user1: " + user1);
Console.WriteLine("user2: " + user2);

retrieve not the contents of any local variable, but the value in notUsed, since both user1 and user2 point to it. So, of course, you'll get "B" twice.

It is no more shocking than this code:

class User {
    public string Name { get; set; }
}

void NotMagic(User user1, User user2) {
    user1.Name = "A";
    user2.Name = "B";

    Console.WriteLine("user1.Name = " + user1.Name);
    Console.WriteLine("user2.Name = " + user2.Name);
}

void Main() {
    User user = new User();
    NotMagic(user, user);
}

You probably wouldn't be surprised if this printed B twice. That there are two different parameters in NotMagic doesn't mean they can't both point to the same thing. Same with out and ref parameters, except that the syntax will hide the extra indirection for you.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.