Я считаю, что это само по себе безопасно (даже без использования volatile), однако могут возникнуть проблемы в зависимости от того, как другие потоки используют свойство Data.
При условии, что вы можете гарантировать, что все другие потоки прочитают и кэшируют значение Data один раз перед выполнением перечисления с ним (и не пытайтесь привести его к более широкому интерфейсу для выполнения других операций), и не делайте предположений о согласованности для второго доступа к собственности, тогда вы должны быть в порядке. Если вы не можете дать такую гарантию (и было бы трудно сделать такую гарантию, если, например, один из пользователей сам является фреймворком через привязку данных, а следовательно, и код, который вы не контролируете), то вы не сможете скажи, что это безопасно.
Например, это будет безопасно:
foreach (var item in x.Data)
{
// do something with item
}
И это было бы безопасно (при условии, что JIT не позволено оптимизировать локальное, что, как я думаю, имеет место ):
var data = x.Data;
var item1 = FindItem(data, a);
var item2 = FindItem(data, b);
DoSomething(item1, item2);
Вышеуказанные два могут воздействовать на устаревшие данные, но это всегда будут согласованные данные. Но это не обязательно будет безопасно:
var item1 = FindItem(x.Data, a);
var item2 = FindItem(x.Data, b);
DoSomething(item1, item2);
Возможно, это был поиск в двух разных состояниях коллекции (до и после того, как какой-то поток ее заменил), поэтому может быть небезопасно работать с элементами, найденными в каждом отдельном перечислении, поскольку они могут не соответствовать друг другу .
Проблема была бы хуже с более широким интерфейсом; например. если данные выставлены IList<T>
, вам также придется следить за согласованностью операций Count и индексатора.