/// <summary> /// Constructs a new instance of <see cref="LazyInitObject{T}"/>. /// </summary> /// /// <param name="initFunc">A delegate that must be called during initialization to obtain the /// object's value.</param> /// <param name="initLock">An object that will be used as a lock to ensure thread safe /// initialization. If this is null, a lock object is created internally and used.</param> /// <param name="recursionHandling">Specifies how accesses to the object within the /// initialization function are handled.</param> public LazyInitObject( Func <T> initFunc, object?initLock = null, LazyInitRecursionHandling recursionHandling = LazyInitRecursionHandling.THROW ) { if (initFunc == null) { throw new ArgumentNullException(nameof(initFunc)); } if (recursionHandling > LazyInitRecursionHandling.RECURSIVE_CALL) { throw new ArgumentOutOfRangeException(nameof(recursionHandling)); } if (initLock == null) { initLock = new object(); } m_value = default(T); m_initFunc = initFunc; m_initLock = initLock; m_recursionHandler = recursionHandling; m_state = LazyInitObjectState.UNINITIALIZED; }
private T _internalGetValue() { if (m_initLock == null) { throw new InvalidOperationException("Cannot access the value of a default-initialized LazyInitObject."); } lock (m_initLock) { LazyInitObjectState state = m_state; if (state == LazyInitObjectState.COMPLETE) { return(m_value !); } if (state == LazyInitObjectState.FAILED) { throw new InvalidOperationException("Cannot access lazy object after initialization failure."); } if (state == LazyInitObjectState.IN_INITIALIZER) { if (m_recursionHandler == LazyInitRecursionHandling.THROW) { throw new InvalidOperationException("Cannot access lazy object in initializer."); } if (m_recursionHandler == LazyInitRecursionHandling.RETURN_DEFAULT) { return(default(T) !); } } m_state = LazyInitObjectState.IN_INITIALIZER; T value; try { value = m_initFunc(); } catch { m_state = LazyInitObjectState.FAILED; m_initFunc = null !; // This will never be called again throw; } m_value = value; m_state = LazyInitObjectState.COMPLETE; m_initFunc = null !; // This will never be called again return(value); } }