// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) // This code is distributed under the GNU LGPL (for details please see \doc\license.txt) using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; namespace ICSharpCode.SharpDevelop.Dom { public interface IFreezable { /// /// Gets if this instance is frozen. Frozen instances are immutable and thus thread-safe. /// bool IsFrozen { get; } /// /// Freezes this instance. /// void Freeze(); } /// /// Base class for immutable objects. Provides implementation for IFreezable that reports the /// object as always-frozen. /// public abstract class Immutable : IFreezable { bool IFreezable.IsFrozen { get { return true; } } void IFreezable.Freeze() { } } public abstract class AbstractFreezable : IFreezable { bool isFrozen; /// /// Gets if this instance is frozen. Frozen instances are immutable and thus thread-safe. /// public bool IsFrozen { get { return isFrozen; } } /// /// Freezes this instance. /// public void Freeze() { if (!isFrozen) { FreezeInternal(); isFrozen = true; } } protected virtual void FreezeInternal() { } protected void CheckBeforeMutation() { if (isFrozen) throw new InvalidOperationException("Cannot mutate frozen " + GetType().Name); } protected static IList FreezeList(IList list) where T : IFreezable { if (list == null || list.Count == 0) return EmptyList.Instance; list = new ReadOnlyCollection(list.ToArray()); foreach (T item in list) { item.Freeze(); } return list; } protected static IList FreezeList(IList list) { if (list == null || list.Count == 0) return EmptyList.Instance; else return new ReadOnlyCollection(list.ToArray()); } protected static IList FreezeList(IList list) { if (list == null || list.Count == 0) return EmptyList.Instance; else return new ReadOnlyCollection(list.ToArray()); } } static class EmptyList { public static readonly ReadOnlyCollection Instance = new ReadOnlyCollection(new T[0]); } }