ASP.NET / C#: Predefined Parameters

In the example below, the parameter "Direction" may be set by the user to any value, although the default value is "North".

Is there a way to pre-define the available parameters so that only one of the following options may be selected? North, South, East, West
using System;
using System.Linq;
using cAlgo.API;
using cAlgo.API.Indicators;
using cAlgo.API.Internals;
using cAlgo.Indicators;

namespace cAlgo
{
    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class NewcBot : Robot
    {
        [Parameter(DefaultValue = "North")]
        public string Direction { get; set; }

        protected override void OnStart()
        {
        }

    }
}

Open in new window

LVL 10
skijAsked:
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

x
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

it_saigeDeveloperCommented:
Ideally, you would specify an enumeration that represents the valid values.
using System;
using System.Collections.Generic;

namespace EE_Q28680792
{
	class Program
	{
		static void Main(string[] args)
		{
			EnumerationBased sample = new EnumerationBased() { Direction = Direction.North };
			sample.Direction = Direction.West;
			Console.WriteLine(sample.Direction);
			Console.ReadLine();
		}
	}

	class EnumerationBased
	{
		public Direction Direction { get; set; }
	}

	enum Direction
	{
		North = 0,
		South = 1,
		East = 2,
		West = 3
	}
}

Open in new window

Which produces this output -Capture.JPGAnd allows for intellisense code completion -Capture.JPGOtherwise, you would have to check against the set value and alert the user that the value is invalid.

Something like:
using System;
using System.Collections.Generic;

namespace EE_Q28680792
{
	class Program
	{
		static void Main(string[] args)
		{
			CheckBased sample = new CheckBased() { Direction = "North" };

			try
			{
				sample.Direction = "Pear";
				Console.WriteLine(sample.Direction);
			}
			catch (Exception ex)
			{
				Console.WriteLine(ex.Message);
			}
			Console.ReadLine();
		}
	}

	class CheckBased
	{
		List<string> allowedDirections = new List<string>() { "NORTH", "SOUTH", "EAST", "WEST" };

		string _direction;

		public string Direction
		{
			get { return _direction; }
			set
			{
				if (!value.Equals(_direction))
				{
					if (allowedDirections.Contains(value.ToUpper()))
						_direction = value;
					else
						throw new ArgumentOutOfRangeException("Direction", string.Format("{0} is not a valid value for Direction.  Please use North, South, East or West.", value));
				}
			}
		}
	}
}

Open in new window

And produces this output -Capture.JPGBear in mind that there are many different ways you can accomplish your goal.  These are just a couple of examples.

-saige-
käµfm³d 👽Commented:
I wouldn't go to all the trouble if what is shown above does the job, but if you really need strings--which you can always call .ToString() on an enum value to get its name--you could define what I like to call a "string enum". You do this via a class which has a private constructor and several static, read-only instances:

e.g.

public class Direction
{
    public string Value { get; private set; }

    private Direction(string value)
    {
        this.Value = value;
    }

    #region Enum Members

    public static readonly Direction North = new Direction("North");
    public static readonly Direction South = new Direction("South");
    public static readonly Direction East = new Direction("East");
    public static readonly Direction West = new Direction("West");

    #endregion
}

Open in new window


Since the constructor is private, you can only instantiate the class from within itself:

Screenshot
This is why all of the static readonly members work. Those members serve as your "enum" values. You still get Intellisense:

Screenshot
And you get reference comparisons rather than string comparisons--which probably is inconsequential if your strings are interned. References comparisons should be about the same level of performance as enum comparisons since both are basically integer comparisons.

When you need the actual value of the enum, you simply refer to the Value member:

string north = Direction.North.Value;

Open in new window


Again, I would only suggest this if the standard enum route isn't what you're after.
it_saigeDeveloperCommented:
Kaufmed, that is a nifty idea.  What do you think of this implementation to add a little extra spice to it?
using System;
using System.Collections.Generic;
using System.Reflection;

namespace EE_Q28680792
{
	class Program
	{
		static void Main(string[] args)
		{
			StringEnumerationBased sample = new StringEnumerationBased() { Direction = Direction.North };
			Console.WriteLine("Let's write out the directions");
			foreach (Direction direction in Direction.AsEnumerable())
				Console.WriteLine(direction);

			Console.WriteLine();
			Console.WriteLine("Let's see if pear matches a direction:");
			foreach (Direction direction in Direction.AsEnumerable())
				Console.WriteLine(direction.Equals("Pear") ? "Pear matches {0}" : "Pear does not match {0}", direction);

			Console.WriteLine();
			Console.WriteLine("Let's write out our sample direction:");
			Console.WriteLine(sample.Direction);

			Console.WriteLine();
			Console.WriteLine("Let's check case matching:");
			foreach (Direction direction in Direction.AsEnumerable())
				Console.WriteLine(direction.Equals("WeSt") ? "WeSt matches {0}" : "WeSt does not match {0}", direction);

			Console.ReadLine();
		}
	}

	class StringEnumerationBased
	{
		public Direction Direction { get; set; }
	}

	public class Direction
	{
		public string Value { get; private set; }

		private Direction(string value)
		{
			Value = value;
		}

		public static readonly Direction North = new Direction("North");
		public static readonly Direction South = new Direction("South");
		public static readonly Direction East = new Direction("East");
		public static readonly Direction West = new Direction("West");

		public static IEnumerable<Direction> AsEnumerable()
		{
			List<Direction> results = new List<Direction>();
			foreach (FieldInfo field in typeof(Direction).GetFields(BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance))
				if (field.GetValue(typeof(Direction)) is Direction)
					results.Add(field.GetValue(typeof(Direction)) as Direction);
			return results;
		}

		public override string ToString()
		{
			return Value;
		}

		public override int GetHashCode()
		{
			return Value != null ? Value.GetHashCode() : 0;
		}

		public override bool Equals(object obj)
		{
			if (obj == null || obj.GetType() != GetType())
				return false;

			return this == (obj as Direction);
		}

		public bool Equals(string value)
		{
			if (value == null || value.GetType() != Value.GetType())
				return false;

			return this == new Direction(value);
		}

		public bool Equals(Direction direction)
		{
			if (object.ReferenceEquals(direction, null))
				return false;

			return this == direction;
		}

		public static bool operator ==(Direction lhs, Direction rhs)
		{
			if (object.ReferenceEquals(lhs, rhs))
				return true;

			if (object.ReferenceEquals(lhs, null) || object.ReferenceEquals(rhs, null))
				return false;

			return (lhs.Value != null && rhs.Value != null) ? string.Compare(lhs.Value, rhs.Value, true) == 0 : false;
		}

		public static bool operator !=(Direction lhs, Direction rhs)
		{
			return !(lhs == rhs);
		}
	}
}

Open in new window

Produces the following output -Capture.JPG-saige-

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
C#

From novice to tech pro — start learning today.