I believe that this is safe in itself (even without variability), however, problems may arise depending on how other threads use the Data property.
Provided that you can guarantee that all other threads will read and cache the Data value once before doing an enumeration on it (and do not try to use it for a wider interface to perform other operations), and not allow consistency for second access to the property, then you should be fine. If you cannot make this guarantee (and it would be difficult to make this guarantee if, for example, one of the users is the card itself through data binding and, therefore, a code that you do not control), then you cannot say that it is safe .
For example, this would be safe:
foreach (var item in x.Data) {
And that would be safe (provided that the JIT does not allow optimizing the local one, which, in my opinion, is like this):
var data = x.Data; var item1 = FindItem(data, a); var item2 = FindItem(data, b); DoSomething(item1, item2);
The above two may work with outdated data, but will always be consistent data. But this will not necessarily be safe:
var item1 = FindItem(x.Data, a); var item2 = FindItem(x.Data, b); DoSomething(item1, item2);
It can be a search for two different states of the collection (before and after some thread replaces it), therefore it is unsafe to work with elements that are in each separate enumeration, since they may not correspond to each other.
The problem will be worse with a wider interface; eg. if Data out IList<T> you will need to keep track of the consistency of Count and indexer operations.