2012-03-20 5 views
11

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

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 
+0

возможно дубликат http://stackoverflow.com/questions/1219664/c-sharp-reference-type-assignment-vs-value-type-assignment –

+1

@Tudor Я думаю, что он ожидает, что значение " abcd ", который должен быть назначен A. –

+0

@Chris Да, я – Marin

ответ

7

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

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

+0

Это неправда.его просто изменение ссылки на переменную «B». Было бы одинаково, если бы b был типа 'List '. – gdoron

+0

Да, я написал это слишком быстро. Я думаю, это делает его немного яснее. – kemiller2002

7

Вот как это работает. Строки являются ссылочным типом: ваша переменная 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" }; 

Это, вероятно, стоит отметить, что она не работает таким образом, для типов значений (целые числа, удвоения, поплавки, длинные, десятичные числа, булевы, структуры и т. д.). Они копируются по значению, если только они не помещены как Object.

2

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

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

2
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 
4

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

+0

+1, для обходного пути. Так просто. – nawfal

0

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

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 
Смежные вопросы