Why is LazyInit <T> limited to reference types
The reason why LazyInit uses the API for routines. It uses Interlocked.CompareExchange to make a stream-protected dataset. CompareExchange while generic is limited to using class types only. Therefore, the T LazyInit value must also be a class.
You can view the implementation here: LazyInit
source to share
Our current (pre) bits only provide the LazyInit type, and as you noticed (and JaredPar is correctly diagnosed), we restrict T to reference types so that we can: (i) make LazyInit a structure and (ii) provide sane defaults via CMPXCHG ( ie we can check that "null" means no value). We could have made T unbounded, but decided to optimize the general case — otherwise it would mean a few extra bytes; believe it or not, it might make this type prohibitively expensive for some people.
We recently changed course a bit. We are currently planning to offer the LazyInit type, where T is unbounded, in addition to the LazyInitField type, where T is limited to reference types. The former is what most people will use, but the latter can be used for those who are persistent and can live with a T.
Hope this clears things up. Cheers,
--- joe duffy, pfx dev lead