C# assign by reference - c#

Is it possible to assign by reference? I know that ref has to be used in methods.
string A = "abc";
string B = A;
B = "abcd";
Console.WriteLine(A); // abc
Console.WriteLine(B); // abcd
Can I have some sort of
string A = "abc";
string B = (ref)A;
B = "abcd"; // A was assigned to B as reference, so changing B is the same as changing A
Console.WriteLine(A); // abcd
Console.WriteLine(B); // abcd

That's how it works already. Strings are a reference type- your variable A is a reference (like a pointer) to a string on the heap, and you are just copying the pointer's value (the address of the string) into the variable B.
Your example doesn't change the value of A when you assign "abcd" to B because strings are treated specially in .net. They are immutable, as Kevin points out- but it is also important to note that they have value type semantics, that is assignments always result in the reference pointing to a new string, and doesn't change the value of the existing string stored in the variable.
If, instead of Strings, you used (for example) cars, and changed a property, you'd see this is the case:
public class Car {
public String Color { get; set; }
}
Car A = new Car { Color = "Red" };
Car B = A;
B.Color = "Blue";
Console.WriteLine(A.Color); // Prints "Blue"
// What you are doing with the strings in your example is the equivalent of:
Car C = A;
C = new Car { Color = "Black" };
It's probably worth noting that it does not work this way for value types (integers, doubles, floats, longs, decimals, booleans, structs, etc). Those are copied by value, unless they are boxed as an Object.

You aren't modifying the reference to A. You are creating a whole new string. A still shows "abc", because it can't be changed by modifying B. Once you modify B, it points to a whole new object. Strings are immutable too, so any change to one creates a new string.
To further answer your question with non-immutable reference types, it is possible to modify the properties of an object that a variable points to and it will show the changed effect when you access other variables pointing to the same object. This does not mean however that you can have a variable point to a brand new object, and have other variables (that pointed to the old object) point to that new object automatically without modifying them as well.

Strings are immutable that's true. However you can resolve your issue by encapsulating string within a class and making A and B instances of that class. Then A = B should work.

public class ReferenceContainer<T>
{
public T Value {get;set;}
public ReferenceContainer(T item)
{
Value = item;
}
public override string ToString()
{
return Value.ToString();
}
public static implicit operator T (ReferenceContainer<T> item)
{
return Value;
}
}
var A = new ReferenceContainer<string>("X");
var B = A;
B.Value = "Y";
Console.WriteLine(A);// ----> Y
Console.WriteLine(B);// ----> Y

Strings are already references, after B = A then B.equals(A) will return true. However, when you do B = "abcd" you're doing the same thing, you're assigning B to a reference to the string literal.
What you are wanting to do is modify the data pointed to by the string, however, because Strings in .NET are immutable there is no way to do that.

Strings are special objects in C# because they are immutable, otherwise it would be by reference. You can run this snippet to see.
public class Foo
{
public string strA;
}
Foo A = new Foo() { strA = "abc" };
Foo B = A;
B.strA = "abcd";
Console.WriteLine(A.strA);// abcd
Console.WriteLine(B.strA);//abcd

All you do is this:
string A = "abc";
ref string B = ref A;
B = "abcd"; // A was assigned to B as reference, so changing B is the same as changing A
Console.WriteLine(A); // abcd
Console.WriteLine(B); // abcd

Related

Why a reference type doesn't update in C#

Here is my c# code. Why a reference type doesn't update in C#, below is the code
class Program
{
public static void Main(string[] args)
{
var a = A.field;
A.field = "2";
Console.WriteLine(a);
Console.Read();
}
}
public static class A
{
public static string field = "1";
}
The result is 1, why??
public static void Main(string[] args)
{
var a = A.field; // `a` is now a reference to the string "1"
A.field = "2"; // `A.field` is now a reference to the string "2"
Console.WriteLine(a); // nothing else has changed, so `a` is still a reference to the string "1"
Console.Read();
}
So the answer to your question is basically: the reference doesn't update, because you're not changing the reference you're writing to the Console (a), but another reference (A.field).
The behaviour you're witnessing is not limited to reference types. The same thing will happen with value types:
int x = 1;
int y = x;
x = 2; // y is still 1 at this point
This happens because the y variable stores the value 1, and changing value of x does not automatically change the value of y. x doesn't "know" about y.
It is the same with reference types - in your example a points to the same location in memory as A.field after the assignment, but it doesn't "know" where A.field points to. Therefore changing the reference of A.field doesn't influence a.
An analogy:
You give Joe a card with Cat written on it. Let Ann = Joe mean that Ann will receive a card from you with the same thing written on it as on Joe's card. So now they both have Cat written on their cards. Now if you give another card to Joe, with Dog written on it, Ann still has Cat on her card. This analogy applies to value types, for reference types you'd have a location written on the card, pointing to the place where they can find the word. The same principle still applies, though.
This is the same as following:
String a = "1";
String b = a;
b = "2";
Console.Write($"a:{a} b:{b}");
Originally you have a variable a that references the object with the content 1, and a variable b that references the same object. Then you modify the variable b to reference a new object, one with content 2. You do not modify the object referenced by a nor b, you make the variable reference a different object. You would have to modify the object referenced by b so that the a variable 'sees' the change. Alas as String is immutable there is simply no method to actually modify it. Any API at your disposal would result in a new string that b would reference, and a would look the same as before. With a mutable type you would see the difference, as long as you modify the object, not simply assign a new object to the variable:
var a = new Widget {x = 1};
var b = a;
b.x = 2;
Console.Write($"a.x: {a.x} b.x: {b.x}");
You are assigning reference and not modifying the original reference.
When you assign A.field to a you assign reference of string "1" to a. Later you assign a new string to A.field and there was no change in the original value of a. It still holds the old reference to string "1".
If somehow, you could modify the original reference then you should be able to see the change. Since your type is string, you can't really modify it because it is immutable, but consider an example with StringBuilder.
public static class A
{
public static StringBuilder field { get; set; } = new StringBuilder("1");
}
And later.
static void Main(string[] args)
{
var a = A.field;
A.field.Insert(0, "2");
Console.WriteLine(a);
Console.Read();
}
Now you will get modified value "21" in variable a as well.
Notice that the code above is modifying the field with A.field.Insert(0, "2"); and since variable a holds the reference to A.field, you see the change on the next line.
But if you try to assign a new reference to A.field with statement like:
A.field = new StringBuilder("2");
Then A.field will have a new object to reference, and the previous variable a will still keep the old reference.
You may think at a "reference" type variable as a box, where it is into an address to some resource.
Let's consider a string value.. when we assign some literal value string to a "reference", we do nothing that:
to allocate a memory area (static or heap) setted with the specified value;
to allocate another memory area (static or heap) initialized with the memory address (reference) of the string value;
When we assign a string "reference" type var to another "reference", we do nothing that to assign the memory address of the referenced string value to the new "reference".
So, if we change the first "reference" with a new assignment statement, the second will not be affected and it continues to reference the original value.
Finally, it is not possible (for now at least) have "references to references" in C#, you can have it in C++ (where pointers and references are a bit different things..). See also this Eric Lippert answer to an analougous question:
https://stackoverflow.com/a/15328414/3762855
The variable a gets a copy of value of the static property A.field.
So when you modify A.field, the copy does not change.
try this
class Program
{
static void Main(string[] args)
{
A.field = "2";
var a = A.field;
Console.WriteLine(a);
Console.Read();
}
}
public static class A
{
public static string field = "1";
}

Explanation to behavior of strings

Objects are reference types; so this code will print out Angelo.
Object o = new Object();
o.Name = "Michael";
Object p = o;
o.Name = "Angelo";
Console.WriteLine(p);
I read that string is a reference type but behaves much like a value type(like int).
int x = 10;
int y = x;
x = 20;
Console.WriteLine(y);
The code above will print 10 because y copies the actual value in the variable x. Now for the string:
string s = "Hello";
string t = s;
s = "Hi";
Console.WriteLine(t);
Now the code above for string will print "Hello". My question is this; since string is a reference type, does string s hold a reference to the object Hello when you declare it?and string t also holds a reference to that object?and the reason why Hi wasn't printed out was because of Immutability?
Or does a string when declared hold the actual value of an object much like value types?like in the second code example.
I want to have a firm grasp of the basics and I am thankful for everyones' patience with the silly questions I post here :)
Let me try to explain line by line what is going on here;
First of all, string is a reference type and reference types have 2 things. An object and a reference to that object.
string s = "Hello";
In this line, you have a "Hello" object and a reference to that object called s.
string t = s;
In this line, you have a reference called t and it refers the same object (which is "Hello") that s refers.
s = "Hi";
In this line, you create a new object called "Hi" and your s reference refers this object now. It doesn't refer the "Hello" object anymore.
Console.WriteLine(t);
Since t still refers to "Hello" object, this string will be printed. Changing the object that s refers doesn't effect it.
and the reason why Hi wasn't printed out was because of Immutability?
No, you are not doing the same thing. If you do:
Object p = o;
p = new Object();
o.Name = "Angelo";
Console.WriteLine(p);
This obviously will not affect the p. So this has nothing to do with immutability. When you assign a new reference, you are throwing away the old one.When you say:
s = "Hi";
It creates a new string object and store it's reference in s.This is default behaviour.
The only exception to this is when you use ref keyword with a reference type parameter it changes it's reference. For example:
void Foo(ref string x)
{
x = "Hi!";
}
string s = "Hello";
Foo(ref s);
// now s is 'Hi!'
Note that if you could change a property of string, you could observe the same behaviour with strings.
You can declare and initialize strings in various ways, as
// Declare without initializing.
string message1;
// Initialize to null.
string message2 = null;
// Initialize as an empty string.
// Use the Empty constant instead of the literal "".
string message3 = System.String.Empty;
The += operator creates a new string that contains the combined contents. That new object is assigned to the variable s1, and the original object that was assigned to s1 is released for garbage collection because no other variable holds a reference to it.
string s1 = "A string is more ";
string s2 = "than the sum of its chars.";
// Concatenate s1 and s2. This actually creates a new
// string object and stores it in s1, releasing the
// reference to the original object.
s1 += s2;
System.Console.WriteLine(s1);
// Output: A string is more than the sum of its chars.
have a look on this link , may solve your issue;
http://msdn.microsoft.com/en-IN/library/ms228362.aspx

C# struct and class variable value

i know that struct is of value type and class is reference type but when i execute the following code why im getting the two different answer
can any one explain a bit
[struct|class] values {
public int x, y;
public values (int x, int y) {
this.x = x;
this.y = y;
}
}
values v = new values(12, 13);
object o = v;
v.x = 2;
Console.WriteLine(((values)o).x);
Outputs
when
it is class : output is 2
it is struct :output is 12
Can any one explain me?
Thanks
The one line that behaves very differently for struct or class is
object o = v;
When Values is a reference type, o becomes a copy of the reference v. There still is only 1 instance of Values.
When Values is a value type, o becomes a reference to the boxed copy of the instance itself. In this case the assignment creates a 2nd instance and you execute v.x = 2 on the original. The copy is not affected.
Your example includes boxing and that is an unnecessary complication, when you use values o = v; you will get the same output. The line then creates a normal copy (2nd instance) without boxing.
To sum it up: the main difference between value and reference type is in copy semantics. You will notice different behaviour in simple assignments (x = y) and in parameter passing (foo(x)).
You can expect gotchas with mutable value types. As an exercise, see what f.Myvalue.x = 2; does with Values as class or struct with
class Foo { public Values MyValue { get; set; } }
When you use a structure and you assign it (or use it as a parameter of a method), you have a brand new copy of your structure.
Whereas, with a class, you assign a reference to the class.
Key line is
object o = v;
When values is struct (or value-type), it causes boxing values. According this (following that link, you can find exactly your question at end :))
Boxing a value of a value-type consists of allocating an object
instance and copying the value-type value into that instance.
So, your value in v is copied. When you unboxing here
Console.WriteLine(((values)o).x);
you get original v value, not v after
v.x = 2;
So, answer for struct (or value-types) is 12.
For class (or reference-types) it's very simple. You are not boxing, just cast to object, so next you are working with this original v and change it value.
Given
SomeStruct s1, s2, s3;
Object o1;
... s1 gets a value somehow, then...
s2 = s1; // Q1
o1 = s1; // Q2
s3 = (SomeStruct)o1; // Q3
statement Q1 will mutate structure s2 by overwriting all of its public and private fields with the values of the corresponding fields in s1. Statement Q2 will generate a new heap object which will act as though it contains a field of type SomeStruct, and will modify that field by overwriting all of its fields with the corresponding fields in s1. Statement Q3 will check whether o1 contains a "boxed" SomeStruct and, if so, will overwrite all the fields of s3 with the corresponding ones from the boxed object.
Note that boxed structures are not usually modified while they sit within heap objects. If one were to say:
var temp = (SomeStruct)o1;
temp.someField = Whatever;
o1 = temp;
that sequence would create a new heap object which would hold a modified copy of the original structure, but the original boxed structure would remain as it was. There are, however, ways a structure within a boxed object can be modified. One should in most cases avoid using such techniques, but one should be aware there's no such thing as a non-trivial immutable structure (a struct with no fields would be immutable, but not very useful). In general, if one wants to be able to refer to a mutable instance of a structure type, it's best to encapsulate it within a simple class object, e.g.
class ExposedFieldHolder<T>
{
public T Value;
public ExposedFieldHolder(T v) {Value = v;}
}
and if one wants to have an immutable instance, one should encapsulate it in an immutable class object
class ImmutableHolder<T>
{
T value;
public T Value { get { return value; } ;
public ImmutableHolder(T v) {value = v;}
override public bool Equals(Object o) {
var other = o as ImmutableHolder<T>;
if (!other) return false;
return Object.Equals(value,other.value);
}
override public int GetHashCode() { return Object.GetHashCode(value); }
}

String reference

If a and b are both references to the same object why doesn't value of a change when we change value of b in part3. And if I assume that (as in part3) that b is dereferenced when I pass it a new literal string ,why doesn't it also dereference in part2 when I pass "foo" litaral string (ReferenceEquals returns true).
//part1
string a = "foo";
string b = a;
System.Console.WriteLine("\na = {0}\nb = {1}", a, b); //a=foo b=foo
System.Console.WriteLine("a == b : {0}", a == b);//True
System.Console.WriteLine("ReferenceEquals(a, b): {0}", ReferenceEquals(a, b));//True
//part2
b = "foo";
System.Console.WriteLine("\na = {0}\nb = {1}", a, b);//a=foo b=foo
System.Console.WriteLine("a == b : {0}", a == b);//True
System.Console.WriteLine("ReferenceEquals(a, b): {0}", ReferenceEquals(a, b));//True
//part3
b = "bar";
System.Console.WriteLine("\na = {0}\nb = {1}", a, b);//a=foo b=bar
System.Console.WriteLine("a == b : {0}", a == b);//False
System.Console.WriteLine("ReferenceEquals(a, b): {0}", ReferenceEquals(a, b));//False
a and b both refer to the same object.
However, you're changing b, not the object.
String objects are immutable and cannot be changed.
When you write b = "foo", you're changing b to refer to a different String instance.
However, string literals are interned, so writing "foo" will always give the same String instance.
You can get two different String instances with the same value by calling String.Copy:
string a = "foo";
string b = "foo";
Console.WriteLine(ReferenceEquals(a, b)); //True
b = String.Copy("foo");
Console.WriteLine(ReferenceEquals(a, b)); //False
If you change something , like a = "newstring"; it means, that 'a' points to new reference.
Strings are immutable -> you cannot change string itself (a[0] = 'b';).
In part2, when you assign some constant used previously, the reference to the old one is used. This is called 'Interning'.
If you did b = "fo" + "o";, the references wouldn't be equal (in this example they would, because compiler optimizes this, but if the string is created other way than directly used, references are the same).
var a = "foo";
var b = "fo";
b = b + "o";
// in this point, the references AREN'T equal.
b = string.Intern(b);
// in this point, the references ARE equal.
"Strings are immutable--the contents of a string object cannot be changed after the object is created, although the syntax makes it appear as if you can do this."
See http://msdn.microsoft.com/en-us/library/362314fe.aspx
a and b are both references to the same thing in part 1
In part 2 the references remain the same because the compiler has worked out in advance you are just reusing the same string literal (a little memory optimisation) and because strings are immutable it knows it is safe to make that optimisation.
In part 3 you are changing the reference to b only. a remains a reference to "foo" as it was before.
a and b both refer to the same object. How can a change, if you are assigning 'a' to 'b' and then changing the value of 'b'

why don't string object refs behave like other object refs?

string a = "a";
string b = a;
string a = "c";
Why does string b still have the value "a" and not "c"?
As string is an object and not a stack value type, what's with this behaviour?
Thanks
You're pointing the variable to something new, it's no different than if you said
Foo a = new Foo();
Foo b = a;
a = new Foo();
// a no longer equal to b
In this example, b is pointing to what a initially referenced. By changing the value of a, a and b are no longer referencing the same object in memory. This is different than working with properties of a and b.
Foo a = new Foo();
Foo b = a;
a.Name = "Bar";
Console.WriteLine(b.Name);
In this case, "Bar" gets written to the screen because a and b still reference the same object.
Let me start by saying that your choices for variables and data are poor. It makes it very difficult for someone to say "the string a in your example..." because "a" could be the content of the string, or the variable containing the reference. (And it is easily confused with the indefinite article 'a'.)
Also, your code doesn't compile because it declares variable "a" twice. You are likely to get better answers if you ask questions in a way that makes them amenable to being answered clearly.
So let's start over.
We have two variables and two string literals.
string x = "hello";
string y = x;
x = "goodbye";
Now the question is "why does y equal 'hello' and not 'goodbye'"?
Let's go back to basics. What is a variable? A variable is a storage location.
What is a value of the string type? A value of the string type is a reference to string data..
What is a variable of type string? Put it together. A variable of type string is a storage location which holds a reference to string data.
So, what is x? a storage location. What is its first value? a reference to the string data "hello".
What is y? a storage location. What is its first value? a reference to the string data "hello", same as x.
Now we change the contents of storage location x to refer to the string data "goodbye". The contents of storage location y do not change; we didn't set y.
Make sense?
why don’t string object refs behave like other object refs?
I deny the premise of the question. String object refs do behave like other object refs. Can you give an example of where they don't?
Part of what confuses people so much about this is thinking of the following as an append operation:
str1 = str1 + str2;
If string were a mutable type, and the above were shorthand for something like this:
str1.Append(str2);
Then what you're asking would make sense.
But str1 = str1 + str2 is not just some method call on a mutable object; it is an assignment. Realizing this makes it clear that setting a = "c" in your example is no different from assigning any variable (reference type or not) to something new.
The below comparison between code that deals with two List<char> objects and code that deals with two string objects should hopefully make this clearer.
var a = new List<char>();
var b = a; // at this point, a and b refer to the same List<char>
b.Add('a'); // since a and b refer to the same List<char> ...
if (b.Contains('a')) { /* ...this is true... */ }
if (a.Contains('a')) { /* ...and so is this */ }
// HOWEVER...
a = new List<char>(); // now a and b do NOT refer to the same List<char>...
if (b.Contains('a')) { /* ...so this is still true... */ }
if (a.Contains('a')) { /* ...but this is not */ }
Compare this with a slightly modified version of the code you posted:
string a = "a";
string b = a; // at this point, a and b refer to the same string ("a")...
if (b == "a") { /* ...so this is true... */ }
if (a == "a") { /* ...and so is this */ }
// REMEMBER: the below is not simply an append operation like List<T>.Add --
// it is an ASSIGNMENT
a = a + "c"; // now they do not -- b is still "c", but a is "ac"
if (b == "a") { /* ...so this is still true... */ }
if (a == "a") { /* ...but this is not */ }
In .Net, a, b and c are reference to the objects and not the objects themselves. When you reset a, you are pointing this reference to a new memory location. The old memory location and any references to it are unchanged.
I guess the OP thinks string objects to be mutable, so something like var = "content";
would actually store the new character array inside the already existing object.
String is, however, an immutable type, which means that in this case a new string object is created and assigned to var.
See for example:
http://codebetter.com/blogs/patricksmacchia/archive/2008/01/13/immutable-types-understand-them-and-use-them.aspx
It is a misunderstanding because of the builtin string support of c#.
string a = "123"; //The way to write it in C#
string a = new string("123"); //Would be more obvious
The second way to define a is more obvious what happens, but it is verbose.Since strings have direct support from the compiler calling the string constructor is unnecessary.
Writing your example verbose:
string a = new string("a");
string b = a;
string a = new string("c");
Here the behavior is as expected a gets a reference to the new string object assigned. while the reference held by b still points to the old string.

Categories

Resources