Store a Reference to a Value Type

Store a reference to a value type?

You cannot store a reference to a variable in a field or array. The CLR requires that a reference to a variable be in (1) a formal parameter, (2) a local, or (3) the return type of a method. C# supports (1) but not the other two.

(ASIDE: It is possible for C# to support the other two; in fact I have written a prototype compiler that does implement those features. It's pretty neat. (See http://ericlippert.com/2011/06/23/ref-returns-and-ref-locals/ for details.) Of course one has to write an algorithm that verifies that no ref local could possibly be referring to a local that was on a now-destroyed stack frame, which gets a bit tricky, but its doable. Perhaps we will support this in a hypothetical future version of the language. (UPDATE: It was added to C# 7!))

However, you can make a variable have arbitrarily long lifetime, by putting it in a field or array. If what you need is a "reference" in the sense of "I need to store an alias to an arbitrary variable", then, no. But if what you need is a reference in the sense of "I need a magic token that lets me read and write a particular variable", then just use a delegate, or a pair of delegates.

sealed class Ref<T> 
{
private Func<T> getter;
private Action<T> setter;
public Ref(Func<T> getter, Action<T> setter)
{
this.getter = getter;
this.setter = setter;
}
public T Value
{
get { return getter(); }
set { setter(value); }
}
}
...
Ref<string> M()
{
string x = "hello";
Ref<string> rx = new Ref<string>(()=>x, v=>{x=v;});
rx.Value = "goodbye";
Console.WriteLine(x); // goodbye
return rx;
}

The outer local variable x will stay alive at least until rx is reclaimed.

Store reference of a value type variable C#

There's no way to store a "ref" to a variable in .NET; that's deliberate. It eliminates the class of bugs common in C / C++, where you store a ref to a variable past its lifetime and bad things happen.

The way to do what you want is instead, pass in an Action<T> that sets the variable (or property) you want to change, and then when you want to change it, you invoke the action.

How then does that solve the problem? Because C# makes sure that the variable captured by the delegate is always long-lived.

Is object a reference type or value type?

It is a reference type

Doing an example with string isn't very illuminating, because string is also a reference type (as is SampleClass, obviously); your example contains zero "boxing".

if object is reference type then why obj2 value is still "OldString"

Why wouldn't it be? When you create a new string, that doesn't change old references to point at the new string. Consider:

 object obj1 = "OldString";
// create a new string; assign obj1 the reference to that new string "OldString"

object obj2 = obj1;
// copy the reference from obj1 and assign into obj2; obj2 now refers to
// the same string instance

obj1 = "NewString";
// create a new string and assign that new reference to obj1; note we haven't
// changed obj2 - that still points to the original string, "OldString"

memory allocation for value type inside reference type in .net

But what about value types present inside a class (reference type)?
Where are they stored and how are they accessed?

Value types are stored where they are declared. In your case, they will be on heap.

But you should see the following articles with respect to memory management in C#.

The Truth about value types - Eric Lippert

in the Microsoft implementation of C# on the desktop CLR, value types
are stored on the stack when the value is a local variable or
temporary that is not a closed-over local variable of a lambda or
anonymous method, and the method body is not an iterator block, and
the jitter chooses to not enregister the value.

The Stack Is An Implementation Detail, Part One - Eric Lippert

Memory in .NET - what goes where - Jon Skeet

Is int[] a reference type or a value type?

Arrays are mechanisms that allow you
to treat several items as a single
collection. The Microsoft® .NET Common
Language Runtime (CLR) supports
single-dimensional arrays,
multidimensional arrays, and jagged
arrays (arrays of arrays). All array
types are implicitly derived from
System.Array, which itself is derived
from System.Object. This means that
all arrays are always reference types
which are allocated on the managed
heap, and your app's variable contains
a reference to the array and not the
array itself.

https://msdn.microsoft.com/en-us/library/bb985948.aspx

How will an object with a value type and reference type be stored in .NET?

Eric Lippert just wrote about this:

It is simply false that the choice of whether to use the stack or the heap has anything fundamentally to do with the type of the thing being stored.

The true story is:

"in the Microsoft implementation of C# on the desktop CLR, value types are stored on the stack when the value is a local variable or temporary that is not a closed-over local variable of a lambda or anonymous method, and the method body is not an iterator block, and the jitter chooses to not enregister the value."

Most importantly, he stresses that you simply should not care where a type lives. You should care where things of a certain lifetime live.

Why reference types inside structs behave like value types?

strings are reference types that have pointers stored on stack while their actual contents stored on heap

No no no. First off, stop thinking about stack and heap. This is almost always the wrong way to think in C#. C# manages storage lifetime for you.

Second, though references may be implemented as pointers, references are not logically pointers. References are references. C# has both references and pointers. Don't mix them up. There is no pointer to string in C#, ever. There are references to string.

Third, a reference to a string could be stored on the stack but it could also be stored on the heap. When you have an array of references to string, the array contents are on the heap.

Now let's come to your actual question.

    Person person_1 = new Person();
person_1.name = "Person 1";
Person person_2 = person_1; // This is the interesting line
person_2.name = "Person 2";

Let's illustrate what the code does logically. Your Person struct is nothing more than a string reference, so your program is the same as:

string person_1_name = null; // That's what new does on a struct
person_1_name = "Person 1";
string person_2_name = person_1_name; // Now they refer to the same string
person_2_name = "Person 2"; // And now they refer to different strings

When you say person2 = person1 that does not mean that the variable person1 is now an alias for the variable person2. (There is a way to do that in C#, but this is not it.) It means "copy the contents of person1 to person2". The reference to the string is the value that is copied.

If that's not clear try drawing boxes for variables and arrows for references; when the struct is copied, a copy of the arrow is made, not a copy of the box.

Dart Variable store reference to the value

Everything is an Object in Dart. Some objects are mutable - that is they can be modified, and some are immutable, that is they will always be the same value.

When you assign with var b = a; both b and a will reference the same Object, but there is no further association between the names b and a. If you mutate that Object by calling methods on it or assigning to fields on it (things like List.add for example) then you will be able to observe the mutated Object through either name b or a. If you assign to a then the variable b is unaffected. This is true in javascript as well.

The reason some types, like numbers or Strings, appear special is that they cannot be mutated, so the only way to "change" a is to reassign it, which won't impact b. Other types, like collections, are mutable and so a.add("Banana") would be a mutation visible through either variable referencing that list.

For example, with assignment:

var a = ['Apple', 'Orange'];
var b = a;
a = ['Banana']; // Assignment, no impact to b
print(a); // [Banana]
print(b); // [Apple, Orange]

With mutation:

var a = ['Apple', 'Orange'];
var b = a;
a.clear(); // Mutation, the _list instance_ is changed
a.add('Banana') // Another mutation
print(a); // [Banana]
print(b); // [Banana]


Related Topics



Leave a reply



Submit