2012-02-19 3 views
0

кажется, что строка является ссылкой, но копируется значениеКак передать строку в коллекцию по ссылке?

List<string> data = new List<string>(); 
string s = "a"; 
data.Add(s); // copy by value?? 
s = "b"; 
Console.WriteLine(data[0]); // "a" 

Кроме того, представляется, что класс ссылка копируется по ссылке

class boxstring { public string val; } 
List<boxstring> data = new List<boxstring>(); 
boxstring s = new boxstring { val = "a" }; 
data.Add(s); // copy by reference, ok 
s.val = "b"; 
Console.WriteLine(data[0].val); // "b" 

Есть более простой способ передать строку в коллекцию с помощью ссылки без упаковки в класс? Я хотел бы передать член объекта в коллекцию, и если объект был изменен, коллекция также должна быть изменена без написания дополнительного кода.

+4

Строка ничем не отличается от любого другого класса. Важной линией является 's =" b ";'. Это переназначение. Обратите внимание, что любой класс будет показывать такое же поведение в списке. * Наблюдаются мутации * экземпляра *. * Переназначения * переменной * не являются. –

+0

Возможный дубликат [C# справочной коллекции для хранения ссылочных типов] (http://stackoverflow.com/questions/4569062/c-sharp-reference-collection-for-storing-reference-types) – nawfal

ответ

1

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

Однако .NET уже предоставляет изменяемый аналог строки i.e "StringBuilder". Это будет работать у вас -

List<StringBuilder> data = new List<StringBuilder>(); 
StringBuilder s = new StringBuilder("a"); 
data.Add(s); 
s.Clear(); 
s.Insert(0, "b"); 
Console.WriteLine(data[0]); // "b" 
+0

О да! Это именно то, что я искал! Большое спасибо! –

2

Строки неизменяемы, если вы хотите, чтобы объекты в вашем контейнере менялись, они должны быть изменены. Поэтому вы должны обернуть их в класс, как вы.

+0

Отсутствие возможности создать нечто вроде указателя нанизывать? –

+0

Это именно то, что вы сделали. Вы можете играть с некоторыми дженериками, чтобы сделать его немного приятнее. – zmbq

-2

Вы не можете передавать встроенные типы данных по ссылке, они всегда передаются по значению. Внутренние типы включают основные типы, такие как Int32, String, Bool, и т.д ..

+0

А как насчет ключевого слова 'ref'? Он позволяет передавать аргумент по ссылке, даже встроенные типы. –

1

Вот идея, чтобы сделать ваш код проще:

public MyString 
{ 
public string Value{get;set;} 
public MyString(string value) 
{ 
Value=value; 
} 



public static implicit operator MyString(string value) 
{ 
return new MyString(value); 
} 

public static implicit operator string(MyString mystring) 
{ 
if(mystring==null) return null; 
return mystring.Value; 
} 

, то вы можете использовать объект MyString всякий раз, когда вы хотите иметь строку по ссылке . Поскольку у нас есть этот неявный оператор, вы можете использовать MyString вместо строки

+1

Это казалось многообещающим, но неявный оператор MyString создает новый экземпляр, поэтому соединение с элементом в List теряется после переназначения нового значения. –

+0

вы можете сохранить MyString в своем списке. И я забыл, что вам не нужна неизменяемая строка :), тогда должен быть способ изменить значение MyString. Я отредактирую источник :) – Beatles1692

+0

Ну, вы правы MyString = «новая строка» не изменит значение одной и той же ссылки, но создает новый экземпляр, поэтому предыдущий экземпляр будет иметь свое предыдущее значение. Похоже, что использование перегрузки оператора не поможет нам в этой ситуации. – Beatles1692

Смежные вопросы