С# присвоить ссылку

Можно ли присвоить ссылку? Я знаю, что ref должен использоваться в методах.

string A = "abc";
string B = A;
B = "abcd";
Console.WriteLine(A); // abc
Console.WriteLine(B); // abcd

Можно ли что-то сделать

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

Ответ 1

Вы не изменяете ссылку на A. Вы создаете целую новую строку. По-прежнему отображается "abc", потому что он не может быть изменен путем изменения B. После изменения B он указывает на целый новый объект. Строки тоже неизменяемы, поэтому любое изменение на один создает новую строку.

Чтобы еще раз ответить на ваш вопрос с помощью неизменяемых ссылочных типов, можно изменить свойства объекта, на который указывает переменная, и он покажет измененный эффект при доступе к другим переменным, указывающим на один и тот же объект. Это не означает, однако, что вы можете иметь переменную точку для совершенно нового объекта и иметь другие переменные (указывающие на старый объект), указывая на этот новый объект автоматически, не изменяя их.

Ответ 2

Как это работает. Строки являются ссылочным типом: ваша переменная A является ссылкой (например, указателем) на строку в куче, и вы просто копируете значение указателя (адрес строки) в переменную B.

Ваш пример не изменяет значение A, когда вы назначаете "abcd" в B, потому что строки обрабатываются специально в .net. Они неизменны, как указывает Кевин, но важно также отметить, что они имеют семантику типа значения, то есть назначения всегда приводят к ссылке, указывающей на новую строку, и не меняют значение существующей строки, хранящейся в переменная.

Если вместо строк вы использовали (например) автомобили и изменили свойство, вы увидите, что это так:

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" };

Возможно, стоит отметить, что он не работает таким образом для типов значений (целые числа, парные, float, longs, decimals, booleans, structs и т.д.). Они копируются по значению, если только они не помечены как Object.

Ответ 3

Строки неизменны, что верно. Однако вы можете решить свою проблему, инкапсулируя строку внутри класса и создавая экземпляры A и B этого класса. Тогда A = B должен работать.

Ответ 4

Строки уже являются ссылками, после B = A, тогда B.equals(A) вернет true. Однако, когда вы делаете B = "abcd", вы делаете одно и то же, вы назначаете B ссылке на строковый литерал.

То, что вы хотите сделать, это изменить данные, на которые указывает строка, однако, поскольку строки в .NET являются неизменными, нет никакого способа сделать это.

Ответ 5

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>("abc");
var B = A;
B.Value = "abcd";
Console.WriteLine(A);//abcb
Console.WriteLine(B);//abcd

Ответ 6

Строки - это специальные объекты в С#, потому что они неизменяемы, иначе это будет ссылка. Вы можете запустить этот фрагмент, чтобы увидеть.

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