You are right that, initially, both x and y reference the same object:
       +-----------+
y   -> |   hello   |
       +-----------+
            ^
x   --------+
Now have a look at this line:
x = x.Replace('h','j');
The following happens:
- x.Replacecreates a new string (with h replaced by j) and returns a reference to this new string.
 -        +-----------+    +------------+
y   -> |   hello   |    |   jello    |
       +-----------+    +------------+
            ^
x   --------+
 
- With - x = ..., you assign- xto this new reference.- ystill references the old string.
 -        +-----------+    +------------+
y   -> |   hello   |    |   jello    |
       +-----------+    +------------+
                              ^
x   --------------------------+
 
So how do you modify a string in-place? You don't. C# does not support modifying strings in-place. Strings are deliberately designed as an immutable data structure. For a mutable string-like data structure, use StringBuilder:
var x = new System.Text.StringBuilder("hello");
var y = x;
// note that we did *not* write x = ..., we modified the value in-place
x.Replace('h','j');
// both print "jello"
Console.WriteLine(x);
Console.WriteLine(y);