I have a class with one property
public class Test
{
public string Name { get; set; }
}
private void TestReference()
{
Test tst1 = new Test();
tst1.Name = "ASP.NET";
Test tst2 = tst1;
tst1.Name = "JAVA";
string name = tst2.Name; // Shows "JAVA" because of reference sharing
tst1 = null;
bool isNullObj = tst2 == null; // isNullObj is false
}
In above example when I set tst.Name = "JAVA" this change also reflect in tst2.Name because of reference sharing, this I understand but when I set tst = null; tst2is still alive.
my question is, if it is sharing reference! why tst2 is still alive?
tst1 and tst2 are variables which hold reference to objects in memory. If both point to same object, then you can change object via any of references.
If you resign a reference to one of variables, the other variable will still hold its reference. That's why setting tst1 to null (or to any other value) does not affect tst2.
Here is what you have in memory:
This (oddly enough) makes more sense when you think of references as pointers.
When I write:
tst1.Name = "JAVA";
I am going through the pointer and modifying the object itself. However, when I write:
tst1 = null;
I am just setting the variable (of pointer type) to null. The object it was pointing to is not affected. Thus,
tst2 == null
Will always return false.
Consider this case, without Reference Types:
int a = 1; // a = 1
int b = a; // a = 1, b = 1
a = 2; // a = 2, b = 1
// a == b -> false
This is the same thing that is happening with the presented code in the question. For reference types, only a reference value (or the "reference to an object") is stored in the variable. However, the variables themselves are separate and reassignment to one does not affect any other variable.
(The "sharing" behavior is explained because multiple variables, as in the question, can contain the same reference value and thus refer to the same object.)
Related
Supose that I have this:
CustomObject myCO1 = new CustomObject();
CustomObject myCO2 = myCO1;
CustomObject myCO3 = new CustomObject();
myCO1 = myCO3;
I would like that myCO2 has the same reference than myCO1, to myCO3. Is there any way to do that?
Thank so much.
No, assigning a new reference just copies the reference value into the new variable. When you change it's reference the other variables that references the same place are not affected.
So in your case, myCO2 references the old location of myCO1. And myCO1 and myCO3 are referencing to same location.
It sounds a little bit like you could use a primer on references and values in C#. Specifically: "If x is a variable and its type is a reference type, then changing the value of x is not the same as changing the data in the object which the value of x refers to"
However, let me edit your example for a bit of clarity:-
CustomObject myCO1 = new CustomObject("A");
CustomObject myCO2 = myCO1;
CustomObject myCO3 = new CustomObject("B");
myCO1 = myCO3;
You can see clearly that myCO2 refers to "A", even after you change myCO1 to refer to "B". This is because while a reference refers to another object, it is itself a value.
There are largely two ways you can achieve the outcome you desire.
The first option is using a reference type (rather than a value) to refer to your CustomObject:-
public sealed class Reference<T>
{
public T Value { get; set; }
}
...
Reference<CustomObject> myCO1 = new Reference<CustomObject>()
{
Value = new CustomObject("A");
};
Reference<CustomObject> myCO2 = myCO1;
CustomObject myCO3 = new CustomObject("B");
myCO1.Value = myCO3;
The second option you have is to encapsulate the logic you require in a method and use the ref keyword
I have a question about how C# works.
m_MyClass = new MyClass();
Dispatcher.m_MyClass = m_MyClass;
If I set m_MyClass = null, will that automatically make Dispatcher.m_MyClass null?
No. The variable assignment is assigning a copy of the reference by value. Changing the variable after the assignment will not affect the Dispatcher.m_MyClass field/property.
No. Assigning a different value to a variable of a reference has no effect on other
references.
Only modifying fields of an instance or using properties or methods which modify those fields will have an effect:
m_MyClass = new MyClass();
Dispatcher.m_MyClass = m_MyClass;
m_MyClass.MyProp = null;
// Dispatcher.m_MyClass.MyProp == null
Looking at this Microsoft article How to: Write a Copy Constructor (C#) and also this Generic C# Copy Constructor, wouldn't it be best/safe to use a reference to the class instance than to use a plain copy of the instance ?
public class Myclass()
{
private int[] row;
public MyClass(ref MyClass #class)
{
for(int i = 0; i<#class.row.Length;i++)
{
this.row[i] = #class.row[i];
}
}
}
What ref actually means:
void Change(SomeClass instance)
{
instance = new SomeClass();
}
void ChangeRef(ref SomeClass instance)
{
instance = new SomeClass();
}
Later...
SomeClass instance = new SomeClass();
Change(instance);
//value of instance remains unchanged here
ChangeRef(ref instance);
//at this line, instance has been changed to a new instance because
//ref keyword imports the `instance` variable from the call-site's scope
I can't see how this functionality would be useful with respect to a copy constructor.
Object by nature is reference not a value type. I do not see any good reason what extra advantage you would get doing it. But yes you might get into problems because of it, consider this -
You created an object and passed it with reference to couple of classes and those classes are now having access to the address of reference itself. Now I have got all the powers to go and change the reference itself with another object's reference. If here, another class had this object it is actually working on some stale object and other classes can not see what changes are being made and you are in chaos.
I do not see any use of doing it, rather it is dangerous. It does not sounds like a OO way of writing code to me.
The ref keyword is used when a method should be allowed to change the location of a reference. Reference types always pass their reference into a method (but the location of the reference cannot be modified via assignment). Values types pass their value.
See: Passing Parameters
Example:
void PassingByReference(List<int> collection)
{
// Compile error since method cannot change reference location
// collection = new List<int>();
collection.Add(1);
}
void ChangingAReference(ref List<int> collection)
{
// Allow to change location of collection with ref keyword
collection = new List<int>();
collection.Add(2);
}
var collection = new List<int>{ 5 };
// Pass the reference of collection to PassByReference
PassingByReference(collection);
// collection new contains 1
collection.Contains(5); // true
collection.Contains(1); // true
// Copy the reference of collection to another variable
var tempCollection = collection;
// Change the location of collection via ref keyword
ChangingAReference(ref collection);
// it is not the same collection anymore
collection.Contains(5); // false
collection.Contains(1); // false
// compare the references use the default == operator
var sameCollection = collection == tempCollection; // false
I have the following classes:
public class DrawableComplexEntity2D
{
public List<GameComponent> Components { get; set; }
// anothers properties, constructor, methods...
}
public class BoardCell : DrawableComplexEntity2D
{
public GoalPersonGroup GoalPersonGroup { get; set; }
public void CreateGoalPersonGroup(Goal groupType)
{
this.GoalPersonGroup = new GoalPersonGroup(groupType)
base.Components.Add(this.GoalPersonGroup);
}
}
So, when i do:
BoardCell cell1 = new BoardCell();
cell1.CreateGoalPersonGroup(Goal.Type1);
BoardCell cell2 = new BoardCell();
cell2.CreateGoalPersonGroup(Goal.Type2);
cell1.GoalPersonGroup = cell2.GoalPersonGroup;
When i update the cell1.GoalPersonGroup with cell2.GoalPersonGroup, the cell1.GoalPersonGroup is updated, but the cell1.GoalPersonGroup that is inside of the base.Components of cell1 doesn`t change and still the value of cell1 instead cell2. Why?
Yes, you are getting confused with references. Assigning a reference variable assigns the thing that is referenced.
eg
string str1 = new String("Hello"); //str1 has a reference to "Hello"
string basestr = str1; //basestr has a reference to "Hello" (NOT str1)
string str2 = new String("Goodbye"); //str2 has a reference to "Goodbye"
str1 = str2; //str1 has a reference to "Goodbye" (basestr still = hello)
Lists, as with all other variables, contain values. With a reference type (which I'm assuming GoalPersonGroup is), the value is a reference. If I have the following:
object a = ...;
object b = ...;
a = b;
All I've done is take the value of b (which is a reference) and copied that value to a. In the case of a reference type, I can perform operations on that value (like calling a.SomeProperty = "foo";) and those same changes in state will be reflected anywhere in the program where that particular reference is stored in a variable. In other words, if I were to inspect the value of b.SomeProperty, it would be "foo".
However, changing the value in the variable does not affect other variables that point to that value (except in the case of a ref parameter).
You've added a value that points to a reference to your List. You've also assigned that same value to a property. These two distinct memory locations contain the same value, and thus point to the same actual object. But later you're just reassigning the value of the property, which means that it now has a different value than what's stored in the list.
You are only changing the reference in the property cell1.GoalPersonGroup, not the one you have added to base.Components. To fix this, you'll have to add code in the setter of GoalPersonGroup to do what you want.
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.
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?
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
Correct.
You can also describe it as the instance variables being a part of the memory area allocated for the instance on the heap.
the VARIABLE p which is an instance of
the Person reference is passed by
VALUE
The variable is actually not an instance of the class. The variable is a reference to the instance of the class. The reference is passed by value, which means that you pass a copy of the reference. This copy still points to the same instance as the original reference.
I think there is some misunderstanding
going on when people say All objects
in .NET are passed by Reference
Yes, that is definitely a misunderstanding. All parameters are passed by value (unless you use the ref or out keywords to pass them by reference). Passing a reference is not the same thing as passing by reference.
A reference is a value type, which means that everything that you ever pass as parameters are value types. You never pass an object instance itself, always it's reference.
When you pass a person, it is making a copy of the reference - do not confuse this with a copy of the object. In other words, it is creating a second reference, to the same object, and then passing that.
When you pass by ref (with the ref/out keyword), it is passing the same reference to the object that you are using in the caller, rather than creating a copy of the reference.
Maybe this some examples can show you differences between reference types and value types and between passing by reference and passing by value:
//Reference type
class Foo {
public int I { get; set; }
}
//Value type
struct Boo {
//I know, that mutable structures are evil, but it only an example
public int I { get; set; }
}
class Program
{
//Passing reference type by value
//We can change reference object (Foo::I can changed),
//but not reference itself (f must be the same reference
//to the same object)
static void ClassByValue1(Foo f) {
//
f.I++;
}
//Passing reference type by value
//Here I try to change reference itself,
//but it doesn't work!
static void ClassByValue2(Foo f) {
//But we can't change the reference itself
f = new Foo { I = f.I + 1 };
}
//Passing reference typ by reference
//Here we can change Foo object
//and reference itself (f may reference to another object)
static void ClassByReference(ref Foo f) {
f = new Foo { I = -1 };
}
//Passing value type by value
//We can't change Boo object
static void StructByValue(Boo b) {
b.I++;
}
//Passing value tye by reference
//We can change Boo object
static void StructByReference(ref Boo b) {
b.I++;
}
static void Main(string[] args)
{
Foo f = new Foo { I = 1 };
//Reference object passed by value.
//We can change reference object itself, but we can't change reference
ClassByValue1(f);
Debug.Assert(f.I == 2);
ClassByValue2(f);
//"f" still referenced to the same object!
Debug.Assert(f.I == 2);
ClassByReference(ref f);
//Now "f" referenced to newly created object.
//Passing by references allow change referenced itself,
//not only referenced object
Debug.Assert(f.I == -1);
Boo b = new Boo { I = 1 };
StructByValue(b);
//Value type passes by value "b" can't changed!
Debug.Assert(b.I == 1);
StructByReference(ref b);
//Value type passed by referenced.
//We can change value type object!
Debug.Assert(b.I == 2);
Console.ReadKey();
}
}
The term "pass by value" is a little misleading.
There are two things you are doing:
1) passing a reference type (Person p) as a parameter to a method
2) setting a refence type variable (Person p2) to an already existing variable (Person p)
Let's look at each case.
Case 1
You created Person p pointing to a location in memory, let's call this location x. When you go into method AppendWithUnderScore, you run the following code:
p.Name = p.Name + "_";
The method call creates a new local variable p, that points to the same location in memory: x. So, if you modify p inside your method, you will change the state of p.
However, inside this method, if you set p = null, then you will not null out the p outside the method. This behavior is called "pass by value"
Case 2
This case is similar to the above case, but slightly different. When you create a new variable p2 = p, you are simply saying that p2 references the object at the location of p. So now if you modify p2, you are modifying p since they reference the same object. If you now say p2 = null, then p will now also be null. Note the difference between this behavior and the behavior inside the method call. That behavioral difference outlines how "pass by value" works when calling methods
The specifications says nothing about where to allocate value types and objects. It would be a correct C# implementation to say allocate everything on the heap and there Atr situations where values are allocated on the heap other than those you write.
int i = 4;
Func dele = ()=> (object)i;
Will result in (a copy of) i being allocated on the heap because the compiler will make it into a member of a class eventhough it's not declared as such. Other than that you're pretty much spot on. And no everything is not passed as reference. It would be closer to the thruth to state that every parameter was passed by value but still not entirely correct (e.g. ref or out).