[Visual Basic .NET version here]

I had the need for a project to quickly design a flexible system that can create boolean flags based on a name and allow for quickly setting/getting the value of them.

My first thought was to implement it as a Dictionary<string, bool>, but I was told that this needed to be serializable, which immediately axed the Dictionary idea as that is -not- serializable [I have tested, if someone finds out otherwise, let me know], so what I decided to do is recreate Dictionary-like attributes using only a List and a Structure.

Along the way, I realized that, as it being a list, I could only access the data using a numerical index:

Code:
List<Flag> list = new List<Flag>;
Flag F = new Flag();
F.Name = "XYZ";
F.Value = false;
list.Add(F);
Console.WriteLine(list[0].Value);
That's fine and dandy, but that doesn't help me when I'm dealing with names, and calling with names, and searching with names. So, I decided to implement System.Collections.Generic.List<FlagCollection.Flag> which gave me some more freedom over what to do with the list.

After working around for awhile, I figured out how to overload the item property, allowing me to change how I searched for data and also what was returned, so the above code could now be transformed:

Code:
List<Flag> list = new List<Flag>;
Flag F = new Flag();
F.Name = "XYZ";
F.Value = false;
list.Add(F);
Console.WriteLine(list["XYZ"]);
Both of those code snippets will produce the exact same result with this class now. I'm not sure how useful this class will be to someone, but I decided to post it up anyways; maybe someone will get some use out of it.

Enough rambling, here's the code.

Code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace FlagCollection
{

    /// <summary>
    /// An implementation if a flag collection system using a Generic List from the collections namespace
    /// </summary>
    public class FlagCollection : System.Collections.Generic.List<FlagCollection.Flag>
    {

        /// <summary>
        /// An individual structure that contains data for a flag.
        /// </summary>
        [Serializable]
        public struct Flag
        {

            /// <summary>
            /// Returns or sets the Name of this flag.
            /// </summary>
            public string Name { get; set; }

            /// <summary>
            /// Returns or sets if the flag is set or not.
            /// </summary>
            public bool Value { get; set; }

        }


        /// <summary>
        /// Adds a new flag to the flag collection. The return value indicates if the flag was successfully added.
        /// </summary>
        /// <param name="Name">The name of the flag to add.</param>
        /// <param name="Value">The value to set the flag to.</param>
        public bool Add(string Name, bool Value)
        {

            //Use a bit of LINQ magic.
            var currentFlags = (from _flags in this where _flags.Name.Equals(Name) select _flags).ToList();

            //Check
            if (currentFlags.Count.Equals(0)) { this.Add(new Flag() { Name = Name, Value = Value }); return true; } else { return false; }

        }

        /// <summary>
        /// Removes a Flag from the collection. The return value indicates if the removal was
        /// successful.
        /// </summary>
        /// <param name="Name">The name of the flag to remove.</param>
        /// <returns></returns>
        public bool Remove(string Name)
        {

            //See if it even exists
            var flagList = (from flag in this where flag.Name.Equals(Name) select flag).ToList();
            
            //Check
            if (flagList.Count.Equals(0)) { return false; } else { this.Remove(flagList[0]); return true; }

        }

        /// <summary>
        /// Checks to see if a flag exists.
        /// </summary>
        /// <param name="Name">The name of the flag to check.</param>
        /// <returns></returns>
        public bool Exists(string Name)
        {
            return (from f in this where f.Name.Equals(Name) select f).ToList().Count.Equals(1);
        }

        /// <summary>
        /// Returns the value of a flag.
        /// </summary>
        /// <param name="Name">The name of the flag to return.</param>
        /// <exception cref="FlagNotFoundException">When thrown, the flag name will be passed.</exception>
        /// <returns>Returns the value of the flag.</returns>
        public bool GetFlagValue(string Name)
        {

            //LINQ Magic
            var flags = (from flag in this where flag.Name.Equals(Name) select flag).ToList();

            //Check
            if (flags.Count.Equals(0)) { throw new FlagNotFoundException(Name); } else { return flags[0].Value; }

        }

        /// <summary>
        /// Sets a flag with a new value. 
        /// </summary>
        /// <param name="Name">The name of the flag to set.</param>
        /// <param name="newValue">The new value of the flag.</param>
        /// <exception cref="FlagNotFoundException">When thrown, the flag name will be passed.</exception>
        /// <returns>A true or false indicating if the flag was set properly.</returns>
        public bool SetFlagValue(string Name, bool newValue)
        {

            //LINQ Magic
            var flags = (from flag in this where flag.Name.Equals(Name) select flag).ToList();

            //Check
            if (flags.Count.Equals(0)) { throw new FlagNotFoundException(Name); } else { this.Remove(Name); this.Add(Name, newValue); return true; }

        }

        /// <summary>
        /// Returns or sets the value of the given flag.
        /// </summary>
        /// <param name="name">The name of the flag.</param>
        /// <returns></returns>
        public bool this[string name]
        {
            get
            {
                return this.GetFlagValue(name);
            }
            set
            {
                if (!this.Exists(name)) { this.Add(new Flag() { Name = name, Value = !object.ReferenceEquals(value, null) ? value : false }); } else { this.SetFlagValue(name, value); }
            }
        }

        /// <summary>
        /// Serializes all current flags to a byte array.
        /// </summary>
        /// <returns></returns>
        public byte[] Save()
        {

            //Build a memory-stream
            System.IO.MemoryStream ms = new System.IO.MemoryStream();

            //Build the serializer
            System.Runtime.Serialization.Formatters.Binary.BinaryFormatter bf = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();

            //Go ahead and save all the data
            bf.Serialize(ms, this);

            //Now get our byte array
            byte[] data = ms.ToArray();

            //Close the array
            ms.Close();

            //Return the data
            return data;

        }

        /// <summary>
        /// Deserializes all data from the byte array to the flags.
        /// </summary>
        /// <param name="data">The data to de-serialize.</param>
        public void Load(byte[] data)
        {

            //Build a memory-stream
            System.IO.MemoryStream ms = new System.IO.MemoryStream(data);

            //Build the deserializer.
            System.Runtime.Serialization.Formatters.Binary.BinaryFormatter bf = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();

            //Get all the data
            var FlagData = bf.Deserialize(ms);

            //close the stream
            ms.Close();
            
            //Clear our current data
            this.Clear();

            //assign the data
            this.AddRange((List<Flag>)FlagData);

        }

    }
    
    /// <summary>
    /// This exception is thrown when the given flag does not exist.
    /// </summary>
    public class FlagNotFoundException : System.Exception 
    {
        string _msg;
        /// <summary>
        /// The name of the flag being checked.
        /// </summary>
        public string Name { get; set; }
        public override string Message { get { return _msg; } }
        public override string ToString()
        {
            return string.Format("{0}{1}{2}", this.Message, Environment.NewLine, this.StackTrace);
            //return base.ToString();
        }

        /// <summary>
        /// Creates a new FlagNotFoundException.
        /// </summary>
        /// <param name="FlagName">The name of the flag.</param>
        public FlagNotFoundException(string FlagName)
        {
            this.Name = FlagName;
            _msg = string.Format("The flag '{0}' was not found in the collection!", FlagName);
        }

    }

}