2016-08-04 2 views
2

Я заметил интересное действие, когда я изменяю список внутри какого-либо метода и исключаю исключение внутри этого метода, а затем из области списка методов не изменяется.Список не изменен вне метода

Как изменить силу, которую этот список необходимо изменить в блоке catch? используя?

List<string> list = null; 
try 
{ 
    list = new List<string>{"1", "2", "3"}; 
    ChangeMyList(list); 
} 
catch 
{ 
    //here list has 3 elements , why ? 
} 

void ChangeMyList(List<string> list) 
{ 
    list = list.Except(new List<string>{"1", "2"}).ToList(); 
    //here this list has only one element 
    throw new Exception(); 
} 
+0

объект Списка был объявлен во внутреннем объеме Ьги блока, так что даже не существует в блоке улове – Fabjan

+0

Ваш код не получает скомпилированные. Как работает код в методе ChangeMyList: Список («1», «2»)? – ehh

+1

Ive обновил ваш код для компиляции. – Jamiec

ответ

5

Внутри ChangeMyList, list является копией ссылки на список источников, на который указывает list во внешней области. Присвоение этой локальной ссылки не влияет на ссылку в вызывающем абоненте. Вы можете использовать ref передать list по ссылке:

void ChangeMyList(ref List<string> list) 
{ 
    list = list.Except(new List<string>("1", "2")).ToList(); 
    //here this list has only one element 
    throw new Exception(); 
} 

затем

List<string> list = new List<string>{"1", "2", "3"}; 
ChangeMyList(ref list); 
+0

wow, я подумал, что если вы пройдете по ссылке, например, через List, тогда, если вы измените внутри, тогда внешняя также будет изменена, напротив, когда вы пройдете по значению типа int ... так, как это работает? – kosnkov

+2

@kosnkov - Вы передаете ссылку с помощью 'ref' или' out', которые вы не делаете в своем вопросе. Параметры передаются по умолчанию по умолчанию, что для ссылочных типов означает, что ссылка копируется, поэтому у вас есть две ссылки на один и тот же объект списка. Вы можете мутировать список через обе ссылки (например, вызывая «Добавить» или «Удалить» в списке), но если вы хотите, чтобы назначения были видимыми в вызывающем, вы должны пройти по ссылке. – Lee

2

Это не из-за исключения; ваш список не изменяется, поскольку ссылка на него копируется при вызове функции, как и в, list в вашей функции - это копия list в родительской области, и любые изменения в ней не будут внесены в исходную ,

У вас есть два решения:

Либо сделать вашу функцию возврата list, и хранить его обратно в исходном переменный:

try { 
    having List<string> list = new List<string>{"1", "2", "3"}; 
    list = ChangeMyList(list); 
} catch() { 
} 


List<string> ChangeMyList(List<string> list) 
{ 
    list = list.Except(new List<string>("1", "2")); 
    return list; 
} 

Или вы можете просто передать свой список с ref ключевым словом, чтобы указать, что функция будет его изменять:

try { 
    having List<string> list = new List<string>{"1", "2", "3"}; 
    ChangeMyList(ref list); 
} catch() { 
} 


void ChangeMyList(ref List<string> list) 
{ 
    list = list.Except(new List<string>("1", "2")); 
} 
+0

wow, я думал, что если вы пройдете по ссылке, как через List List, то, если вы измените внутри, тогда внешняя также будет изменена, напротив того, когда вы пройдете по значению, например int ... так, как это работает? – kosnkov

+0

* список * не скопирован, его * ссылка на список *, который копируется - это вводящий в заблуждение ответ. – Jamiec

1

Ответ уже дан, но только для тех, кто, как и я, го лучше в графическом виде:

enter image description here

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