Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
160 views
in Technique[技术] by (71.8m points)

c# - .NET Parameter passing - by reference v/s by value

I'm trying to validate my understanding of how C#/.NET/CLR treats value types and reference types. I've read so many contradicting explanations I stil

This is what I understand today, please correct me if my assumptions are wrong.

Value types such as int etc live on the stack, Reference types live on the managed heap however if a reference type has for example has an instance variable of type double, it will live along with its object on the heap

The second part is what I am most confused about.

Lets consider a simple class called Person.

Person has a property called Name.

Lets say I create an instance of Person in another class, we'll call it UselessUtilityClass.

Consider the following code:

class UselessUtilityClass
{
   void AppendWithUnderScore(Person p)
   {
     p.Name = p.Name + "_";
   }
}

and then somewhere we do:

Person p = new Person();
p.Name = "Priest";
UselessUtilityClass u = new UselessUtilityClass();
u.AppendWithUnderScore(p);

Person is a reference type, when passed to UselessUtilityClass -- this is where I go - nuts...the VARIABLE p which is an instance of the Person reference is passed by VALUE, which means when I write p.Name I will see "Priest_"

And then if I wrote

Person p2 = p;

And I do

p2.Name = "Not a Priest";

And write p's name like below I will get "Not a Priest"

Console.WriteLine(p.Name) // will print "Not a Priest"

This is because they are reference types and point to the same address in memory.

Is my understanding correct?

I think there is some misunderstanding going on when people say All objects in .NET are passed by Reference, this doesn't jive based on what I think. I could be wrong, thats why I have come to the Stackers.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Value types such as int etc live on the stack. Reference types live on the managed heap however if a reference type has for example has an instance variable of type double, it will live along with its object on the heap

No, this is not correct. A correct statement is "Local variables and formal parameters of value type which are neither directly in an iterator block nor closed-over outer variables of a lambda or anonymous method are allocated on the system stack of the executing thread in the Microsoft implementation of the CLI and the Microsoft implementation of C#."

There is no requirement that any version of C# or any version of the CLI use the system stack for anything. Of course we do so because it is a convenient data structure for local variables and formal parameters of value type which are not directly in an iterator block or closed-over outer variables of a lambda or anonymous method.

See my articles on this subject for a discussion of (1) why this is is an implementation detail, and (2) what benefits we get from this implementation choice, and (3) what restrictions the desire to make this implementation choice drives into the language design.

http://blogs.msdn.com/ericlippert/archive/2009/04/27/the-stack-is-an-implementation-detail.aspx

http://blogs.msdn.com/ericlippert/archive/2009/05/04/the-stack-is-an-implementation-detail-part-two.aspx

Person is a reference type, when passed to UselessUtilityClass -- this is where I go - nuts...

Take a deep breath.

A variable is a storage location. Each storage location has an associated type.

A storage location whose associated type is a reference type may contain a reference to an object of that type, or may contain a null reference.

A storage location whose associated type is a value type always contains an object of that type.

The value of a variable is the contents of the storage location.

the VARIABLE p which is an instance of the Person reference is passed by VALUE,

The variable p is a storage location. It contains a reference to an instance of Person. Therefore, the value of the variable is a reference to a Person. That value -- a reference to an instance -- is passed to the callee. Now the other variable, which you have confusingly also called "p", contains the same value -- the value is a reference to a particular object.

Now, it is also possible to pass a reference to a variable, which many people find confusing. A better way to think about it is when you say

void Foo(ref int x) { x = 10; }
...
int p = 3456;
Foo(ref p);

what this means is "x is an alias for variable p". That is, x and p are two names for the same variable. So whatever the value of p is, that's also the value of x, because they are two names for the same storage location.

Make sense now?


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...