views:

220

answers:

3

I have a pseudo-realtime data processing application where I would like to use LazyInit<double> so I don't do calculations I don't need, but LazyInit<T> restricts T to classes. I can work around it, but I'd obviously prefer not to.

Does anybody know why this is?

A: 

I believe it is because value types are automatically initialized and LazyInit determines if something needs initializing based on if it is null or not. You can get around it by using nullable types.

LazyInit<double?>
Rob Prouse
If there's a T : class constraint then it won't be satisfied by a nullable value type.
Jon Skeet
Unless nullable is also in the constraints, no?
Dalin Seivewright
+2  A: 

The reason why is an underyling API choice in the LazyInit. It uses Interlocked.CompareExchange in order to do a thread safe value set. CompareExchange while generic is constrained to only use class types. Therefore the T value of LazyInit must also be a class.

You can view the implementation here: LazyInit

JaredPar
+3  A: 

Our current (preview) bits only provide a LazyInit type, and as you observed (and JaredPar correctly diagnosed) we restrict T to reference types so that we can: (i) make LazyInit a struct, and (ii) provide reasonable default behavior via CMPXCHG (i.e., we can check for 'null' to mean the absence of a value). We could have made T unrestricted, but decided to optimize for the common case -- doing otherwise would have meant a few extra bytes; believe it or not, this might've made the type prohibitively expensive for some folks.

We've recently changed course slightly. We currently plan to offer a LazyInit type where T is unrestricted in addition to a LazyInitField type where T is restricted to reference types. The former is what most people will use, but the latter can be used for those who are perf-conscious and can live with the restriction on T.

Hope this clears things up. Cheers,

---joe duffy, pfx dev lead