File: System\ServiceModel\MostlySingletonList.cs
Project: ndp\cdf\src\WCF\ServiceModel\System.ServiceModel.csproj (System.ServiceModel)
//------------------------------------------------------------
// Copyright (c) Microsoft Corporation.  All rights reserved.
//------------------------------------------------------------
 
namespace System.ServiceModel
{
    using System.Collections.Generic;
    using System.IdentityModel;
 
    // Embed this struct in a class to represent a field of that class
    // that is logically a list, but contains just one item in all but
    // the rarest of scenarios.  When this class must be passed around
    // in internal APIs, use it as a ref parameter.
    struct MostlySingletonList<T> where T : class
    {
        int count;
        T singleton;
        List<T> list;
 
        public T this[int index]
        {
            get
            {
                if (this.list == null)
                {
                    EnsureValidSingletonIndex(index);
                    return this.singleton;
                }
                else
                {
                    return this.list[index];
                }
            }
        }
 
        public int Count
        {
            get { return this.count; }
        }
 
        public void Add(T item)
        {
            if (this.list == null)
            {
                if (this.count == 0)
                {
                    this.singleton = item;
                    this.count = 1;
                    return;
                }
                this.list = new List<T>();
                this.list.Add(this.singleton);
                this.singleton = null;
            }
            this.list.Add(item);
            this.count++;
        }
 
        static bool Compare(T x, T y)
        {
            return x == null ? y == null : x.Equals(y);
        }
 
        public bool Contains(T item)
        {
            return IndexOf(item) >= 0;
        }
 
        void EnsureValidSingletonIndex(int index)
        {
            if (this.count != 1 || index != 0)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("index"));
            }
        }
 
        bool MatchesSingleton(T item)
        {
            return this.count == 1 && Compare(this.singleton, item);
        }
 
        public int IndexOf(T item)
        {
            if (this.list == null)
            {
                return MatchesSingleton(item) ? 0 : -1;
            }
            else
            {
                return this.list.IndexOf(item);
            }
        }
 
        public bool Remove(T item)
        {
            if (this.list == null)
            {
                if (MatchesSingleton(item))
                {
                    this.singleton = null;
                    this.count = 0;
                    return true;
                }
                else
                {
                    return false;
                }
            }
            else
            {
                bool result = this.list.Remove(item);
                if (result)
                {
                    this.count--;
                }
                return result;
            }
        }
 
        public void RemoveAt(int index)
        {
            if (this.list == null)
            {
                EnsureValidSingletonIndex(index);
                this.singleton = null;
                this.count = 0;
            }
            else
            {
                this.list.RemoveAt(index);
                this.count--;
            }
        }
    }
}