13

Is it possible to specify that a enum property can only have a range of values?

enum Type
{
    None,
    One,
    Two,
    Three
}

class Object
{
    [AllowedTypes(Type.One,Type.Three)]
    Type objType { get; set; }
}

Something like this? Maybe some validator in enterprise library that I don't know of ?!

Ty

14
  • 5
    This defeats the whole purpose of an enum. It is a collection of allowable values. Commented May 15, 2014 at 13:04
  • 2
    An enum is already supposed to be range of allowed values. Commented May 15, 2014 at 13:05
  • 10
    ... and you'd never want to restrict that to a subset for a particular property, guys? Commented May 15, 2014 at 13:06
  • 2
    No, I would create a second (or third) enum. @rawling Commented May 15, 2014 at 13:08
  • 6
    @CodyGray but that makes the values instances of different types, which can be very inconvenient. Commented May 15, 2014 at 13:10

4 Answers 4

8

You could do the validation in setter logic.

EDIT: some example:

class Object
{
    private Type _value;

    public Type objType{ 

        get{ return _value; }
        set{
            if(value != Type.One && value != Type.Three)
                throw new ArgumentOutOfRangeException();
            else
                _value = value;
        }
    }
}
Sign up to request clarification or add additional context in comments.

2 Comments

I second this one, before writing it to the backing field you could add some validation. This does answer the question, but i would not recommend such logic...
@MrMichael what would you recommend instead?
1

Same as st4hoo's solution, only with reflection. You can make it as crazy as you would like.

using System;
using System.Linq;

namespace ConceptApplication
{
    static class Program
    {
        static void Main(string[] args)
        {
            var foobar = new Foobar
            {
                SomeProperty = Numbers.Five
            };
        }
    }

    public class Foobar
    {
        private static Numbers _someProperty;

        [NumberRestriction(Allowed = new[] {Numbers.One, Numbers.Two})]
        public Numbers SomeProperty
        {
            get { return _someProperty; }
            set
            {
                RestrictionValidator.Validate(this, "SomeProperty", value);

                _someProperty = value;
            }
        }
    }

    public class NumberRestriction : Attribute
    {
        public Numbers[] Allowed { get; set; }
    }

    public static class RestrictionValidator
    {
        public static void Validate<T>(T sender, string propertyName, Numbers number)
        {
            var attrs = sender.GetType().GetProperty(propertyName).GetCustomAttributes(typeof(NumberRestriction), true);

            if (attrs.OfType<NumberRestriction>().Any(attr => !(attr).Allowed.Contains(number)))
                throw new ArgumentOutOfRangeException();
        }
    }

    public enum Numbers
    {
        One,
        Two,
        Three,
        Four,
        Five
    }
}

Comments

1

Another way to approach this is through front-end validation / filtering. I encountered a scenario where, on the db level, I needed to allow the db to save a field to any of the enum values, but I didn't want the end user to see invalid options. So, I created an attribute for the enum values specifying what kind of user could see those enum values.

public class FieldAttribute : Attribute
{
    public int FilterProperty { get; set; }
}

Then I decorated the enum values with that attribute.

public enum myEnum{

    ZeroValue,

    [Field(FilterProperty = 0)]
    FirstValue,

    [Field(FilterProperty = 1)]
    SecondValue,

    [Field(FilterProperty = 0)]
    ThirdValue,

    [Field(FilterProperty = 1)]
    FourthValue,
}

then i created an extension method that provided a dictionary of only the values that type of user could see.

        public static IDictionary<int, string> PrepareAcceptableValues(int filterVal) {
        var values = Enum.GetValues(typeof(myEnum));

        var retval = new List<myEnum>();
        foreach (var value in values) {

            try { //if enum value has an attribute type...
                var assignedFilterProp = value.GetType().GetMember(value.ToString()).First().GetCustomAttribute<FieldAttribute>().FilterProperty;

                if (assignedFilterProp.Equals(filterVal)) //if enum value has the correct filter property
                    retval.Add((myEnum)value); //add it in
            }
            catch (Exception e) {
                retval.Add((myEnum)value); //if enum value has no attribute, add it in
            }
        }

        return retval.ToDictionary(i => (int)i, i => i.toString());

Then, when the data came in on the front end, as long as whatever they pick is part of the base enum, the DB can save it.

Not really answering your question directly, but an indirect route that might help you get what you're after.

Comments

0

You could do a workaround like this:

static MyEnumType[] allowedEnumTypes = {MyEnumType.One, MyEnumType.Two};

MyEnumType _myEnumObject = allowedEnumTypes.First();
MyEnumType MyEnumObject
{
    get
    {
        return _myEnumObject;
    }
    set
    {
        if(!allowedEnumTypes.Any (et => et == value))
        {
            throw new Exception("Enum value not allowed.");
        }
        _myEnumObject = value;
    }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.