Be Lazy, but be ware of initialization exception

.Net 4 intro­duced the Lazy<T> type which allows you to cre­ate an object that can be lazi­ly ini­tial­ized so that you can delay the cre­ation of large objects, for instance.

How­ev­er, if your ini­tial­iza­tion log­ic has the poten­tial to except at run­time (e.g. time out excep­tions read­ing from some exter­nal data source) then you should pay close atten­tion to which con­struc­tor you use to cre­ate a new instance of the Lazy<T> type. Depend­ing on the select­ed LazyThread­Safe­t­y­Mode, excep­tions in the ini­tial­iza­tion code might be cached and rethrown on all sub­se­quent attempts to fetch the lazi­ly ini­tial­ized val­ue. Whilst this ensures that threads will always get the same result, hence remov­ing ambi­gu­i­ty, it does mean that you’ve got only one shot at ini­tial­iz­ing that val­ue…



In cas­es where you need to be able to tol­er­ate occa­sion­al ini­tial­iza­tion errors (e.g. read­ing a large object from S3 can fail from time to time for a num­ber of rea­sons) and be able to try again at a sec­ond attempt, the rule of thumb is to instan­ti­ate the Lazy<T> type by set­ting LazyThread­Safe­t­y­Mode to Pub­li­ca­tionOn­ly. In Pub­li­ca­tionOn­ly thread safe­ty mode, mul­ti­ple threads can invoke the ini­tial­iza­tion log­ic but the first thread to com­plete the ini­tial­iza­tion suc­cess­ful­ly sets the val­ue of the Lazy<T> instance.

For exam­ple, the fol­low­ing only works under the Pub­li­ca­tionOn­ly mode:



F# pro­vides a slight­ly nicer syn­tax for defin­ing a lazy com­pu­ta­tion:


the Control.Lazy<T> type is an abbre­vi­a­tion of the BCL Lazy<T> type with a Force exten­sion method which under the hood just calls Lazy<T>.Value.

Pre­sum­ably the above trans­lates rough­ly to the fol­low­ing C# code:

var x = 10;

var result = new Lazy<int>(() => x + 10);

and the thread safe­ty mode using the Lazy(Func<T>) con­struc­tor is LazyThreadSafetyMode.ExecutionAndPublication which caches and rethrows any excep­tions caught in the ini­tial­iza­tion. E.g.: