2013-06-30 16 views
4
public class Foo 
{ 
    public static List<long> myList = new List<long>() { 1,2,3 } 
} 

В другом методе:Incosistent поведение Список <long> собственности

var testList = Foo.myList; 

Если я ставлю точку останова в последней строке и проверить testList это дает мне разные длины, время от времени.

Когда я использую ToList() на Foo.myList, кажется, что он ведет себя правильно. Но почему?

Edit:

Моя проблема заключалась в том, что я сделал вызов Ajax> модифицирована Foo.myList> новый Ajax вызова> еще раз принес Foo.myList и получил измененное значение.

+2

Потому что вы сделали изменить его в другой метод? Проверьте все добавления и удаления вызовов на них и где вы передаете ссылку. Были ли добавлены или удалены элементы? Это может помочь сузить проблему. Чтобы быть в безопасности, вы можете сделать это должным образом, чтобы вернуть копию списка, чтобы вы могли быть уверены, что никто не модифицирует его случайно. –

+0

Если вы не уверены, что можете вывести из списка и переопределить методы «Добавить и удалить», чтобы выбросить execeptions. Затем замените свой список на свой ReadOnlyList. Это даст вам непосредственное представление о том, где происходит изменение. –

ответ

8

Состояние гонки в общем состоянии. Элемент статического поля означает, что есть один экземпляр, поэтому, если вы манипулируете списком в своем коде, он изменяется для ВСЕ потоков, используя это свойство. ToList() работает, потому что он создает копию списка, который не изменит первоначальный список, но учтите, что эта копия также указывает на те же объекты, что и в исходном списке, если объекты являются ссылочными типами. Поэтому изменение ссылочных типов в копии также изменит значения в исходном списке ... но так как long - тип значения, который здесь не применим.

Если вы хотите, чтобы ваш список будет доступен только для чтения http://msdn.microsoft.com/en-us/library/e78dcd75.aspx

+1

Хорошо, я был уверен, что не изменил его. Но я снова исследую этот код с учетом этого. Спасибо – Johan

+0

Если он меняется, вы его изменили. : D – Haney

+0

Я щелкнул правой кнопкой мыши 'Foo.myList'>" find usages ". Результат: «это единственное использование» ... – Johan

3

Это звучит, как вы изменяете Foo.myList или ссылку на него где-нибудь. Обратите внимание, что назначение списка локальной переменной не создает копию. Таким образом:

var list = new List<long> { 1, 2, 3 }; 
var testList = list; 
testList.Add(4); // list is now [1, 2, 3, 4] 
list.Add(5); // testList is now [1, 2, 3, 4, 5] 

С другой стороны, ToList() делает копию. В общем, это, вероятно, самый безопасный, чтобы сделать какие-либо статические списки только для чтения (если это семантику вы хотите), чтобы этого не происходит случайно:

public class Foo { 
    // pre .NET 4.5, use ReadOnlyCollection<T> (which implements IList<T>) 
    public static readonly IReadOnlyList<long> myList = new List<long> { 1, 2, 3 }.AsReadOnly(); 
} 

var testList = Foo.myList.ToList(); // get an editable copy 
var testList2 = Foo.myList; // get a reference to the immutable static list 
+0

Спасибо, какая разница между 'readonly' и' const' здесь? – Johan

+0

@Johan в C#, const может использоваться только с константами времени компиляции, такими как целые числа и строки. Readonly просто предотвращает назначение вне конструктора/статического инициализатора. Проверьте http://stackoverflow.com/questions/755685/c-static-readonly-vs-const. – ChaseMedallion

+0

Еще раз спасибо за помощь, я обновил свой вопрос, если вас интересует источник проблем. – Johan

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