Recently I used this pattern to create a list of properties, each property having a varying number of arguments. The properties list can be made at compile time, it does not need to change at runtime.I tried to code this in a way such that it was easy for me to edit to add in additional properties (i.e., easy to add in a Video Card with arguments Brand, and Cost). This would be part of an application, e.g., this could be implemented by having a property editor dialog which showed the property name, and 3 text boxes with labels showing the names of the properties they are editing. The constructor for clsProperty has a lot of exceptions it can throw, it's probably not necessary since this can only be changed at compile time, but I put them in for completeness and to demonstrate what could go wrong if there was a typo in the code that made the properties list; let me know if you think there is a better way to do error handling in this case. It would be nice to have at least some sort of warning if the parameters aren't right but I'm not sure if exceptions are the right thing to use here.I think I saw that a list of Object is usually frowned upon, let me know if this is a valid time to use that, or if there is an alternative in this case.Any general suggestions to improve readability would be helpful too.For the sake of this example assume that everything in clsProperty is for display purposes only, no code will be doing something like if(Property.Name == ...)using System;using System.Collections.Generic;namespace csParseTest{    internal class clsProperty    {        // is it worth making these fields into properties of clsProperty?        internal readonly   string          Name;                internal readonly   List<string>    ArgNames       = new List<string>();        internal readonly   List<Type>      ArgTypes       = new List<Type>();        internal readonly   List<Object>    ArgDefaults    = new List<Object>();        private List<Object> ArgValues = new List<Object>();        internal clsProperty(string iName, List<string> iArgNames, List<Type> iArgTypes, List<Object> iArgDefaults)        {            if (string.IsNullOrWhiteSpace(iName))            {                throw new ArgumentException(Property must have a valid name.);            }            this.Name = iName;            bool tParameterLengthsOK =  (                                            (iArgNames.Count == iArgTypes.Count) &&                                             (iArgTypes.Count == iArgDefaults.Count)                                        );            if (!tParameterLengthsOK)            {                throw new ArgumentException(Each argument must have a name, type, and default value.);            }            for (int tArgumentIndex = 0; (tArgumentIndex < iArgNames.Count); tArgumentIndex++)            {                string  tArgName        = iArgNames[tArgumentIndex];                Type    tArgType        = iArgTypes[tArgumentIndex];                object  tDefaultValue   = iArgDefaults[tArgumentIndex];                if(tDefaultValue == null)                {                    throw new ArgumentException(Argument  + tArgumentIndex + : no default value.);                }                if (String.IsNullOrWhiteSpace(tArgName))                {                    throw new ArgumentException(Argument  + tArgumentIndex + : name must not be blank.);                }                if (!IsValidArgType(tArgType))                {                    throw new ArgumentException(Argument  + tArgumentIndex + : type  + tArgType.ToString() +  is not supported.);                }                this.ArgNames.Add(tArgName);                this.ArgTypes.Add(tArgType);                this.ArgDefaults.Add(tDefaultValue);                this.ArgValues.Add(tDefaultValue);            }        }        internal void SetArgument(int iArgIndex, string iValueString)        {                      if ((iArgIndex < 0) || (iArgIndex > (ArgValues.Count - 1)))            {                throw new IndexOutOfRangeException(Argument index  + iArgIndex +  is invalid, arguments list has  + ArgValues.Count +  items.);            }            Object  tValue      = null;            Type    tArgType    = this.ArgTypes[iArgIndex];            if (TryParseArgValue(iValueString, tArgType, out tValue))            {                this.ArgValues[iArgIndex] = tValue;            }            else            {                throw new ArgumentException(Could not parse string  + iValueString +  as argument type  + tArgType.ToString());            }        }        // for the sake of this example assume that properties can only be one of these types.        internal static bool IsValidArgType(Type iType)        {            return                (                    (iType == typeof(System.String))  ||                    (iType == typeof(System.Int32))     ||                    (iType == typeof(System.Int64))    ||                    (iType == typeof(System.Single))   ||                    (iType == typeof(System.Double))                );                  }        private static bool TryParseArgValue(string iValueString, Type iParseAsType, out object qValue)        {            qValue = null;            if (iParseAsType == typeof(System.String))            {                qValue = iValueString;                return true;            }            else if (iParseAsType == typeof(System.Int32))            {                int tParsedInt;                if (int.TryParse(iValueString, out tParsedInt))                {                    qValue = tParsedInt;                    return true;                }                else                {                    return false;                }            }            else if (iParseAsType == typeof(System.Int64))            {                long tParsedLong;                if (long.TryParse(iValueString, out tParsedLong))                {                    qValue = tParsedLong;                    return true;                }                else                {                    return false;                }            }            else if (iParseAsType == typeof(System.Single))            {                float tParsedFloat;                if (float.TryParse(iValueString, out tParsedFloat))                {                    qValue = tParsedFloat;                    return true;                }                else                {                    return false;                }            }            else if (iParseAsType == typeof(System.Double))            {                double tParsedDouble;                if (double.TryParse(iValueString, out tParsedDouble))                {                    qValue = tParsedDouble;                    return true;                }                else                {                    return false;                }            }            else            {                // I considered throwing an exception here                return false;            }        }    };    class Program    {        // for the sake of this example assume that this properties list does not need to be changed at runtime.        private static readonly List<clsProperty> AllProperties = new List<clsProperty>        {            new clsProperty(Optical Drive,                                new List<string>    {Brand,                   Speed,                Format},                                new List<Type>      {typeof(System.String),     typeof(System.Single),   typeof(System.String)},                             new List<Object>    {Asus,                    220.3,                  BD-ROM}),            // or with named parameters...            new clsProperty(iName:Hard Drive,                              iArgNames:new List<string>      {Type,                        Price},                                iArgTypes: new List<Type>       {typeof(System.String),         typeof(System.Double)},                             iArgDefaults: new List<Object>  {Solid State Drive,           123.4})        };        // test code        static void Main(string[] args)        {            // e.g., user edits values using text boxes (or a data grid maybe),            // then hits OK or apply            AllProperties[0].SetArgument(0, Lite-On);            AllProperties[0].SetArgument(1, 100.9);            AllProperties[0].SetArgument(2, DVD-ROM);            //Properties[0].SetArgument(1, ShouldFail);            return;        }    }}EDIT: This would be using Winforms for the GUI
User editable properties with varying number of arguments
c#;winforms
Is it about web or windows UI? WPF or WinForms: you could just use PropertyGrid - it is the same component you have in Visual Studio to edit properties. To define properties at runtime if happens to be needed - see TypeDescriptor. 