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.