枚举超出范围

时间:2016-01-10 00:35:37

标签: c# enums

在我的测试函数中处理无效枚举的最佳方法是什么。该功能旨在让我比较两个项目是否相互兼容。理想情况下,如果索引超出范围,我希望返回false。

public enum VNodeClassID
        {
            Default,
            Apple,
            Orange,
            Grape,
            BlueBerry,
            Watermellon,
            // more items to be added
        }

        // square 2d array
        bool[,] validation = new bool[,] 
        { 
            { false, true, true, false, true, true }, 
            { false, false, true, true, false, true }, 
            { false, true, true, false, true, true }, 
            { false, true, false, true, true, false },
            { false, true, true, true, false, true },
            { false, false, true, false, true, true }
        };

        public void Test()
        {
            var itemA = VNodeClassID.Default;
            var itemB = VNodeClassID.Watermellon;
            bool results = validation[(int)itemA, (int)itemB];

            Console.WriteLine("{0}: {1}-{2}", results, itemA, itemB);            
        }

4 个答案:

答案 0 :(得分:2)

您可以这样做:

var valid_values =
    Enum.GetValues(typeof (VNodeClassID)) //Get all valid values of VNodeClassID
    .Cast<VNodeClassID>()
    .ToList(); 

bool results =
    valid_values.Contains(itemA) && //itemA is within range
    valid_values.Contains(itemB) && //itemB is within range
    validation[(int)itemA, (int)itemB];

答案 1 :(得分:2)

您可以编写一个方法来返回项目是否兼容,如下所示:

public bool IsCompatible(VNodeClassID itemA, VNodeClassID itemB)
{
    if (!Enum.IsDefined(typeof(VNodeClassID), itemA))
        return false;

    if (!Enum.IsDefined(typeof(VNodeClassID), itemB))
        return false;

    return validation[(int)itemA, (int)itemB];
}

然后你的测试方法如下:

public void Test()
{
    var itemA = VNodeClassID.Default;
    var itemB = VNodeClassID.Watermellon;
    bool results = IsCompatible(itemA, itemB);

    Console.WriteLine("{0}: {1}-{2}", results, itemA, itemB);            
}

答案 2 :(得分:1)

我建议使用[FlagsAttrbute]并存储一个字典,其中包含与true对应的位。类似下面的代码:

[Flags]
public enum VNodeClassID
{
    Default = 0,
    Apple = 1 << 0,         // Apple = 1
    Orange = 1 << 1,        // Orange = 2
    Grape = 1 << 2,         // Grape = 4
    BlueBerry = 1 << 3,     // Bluebery = 8
    Watermellon = 1 << 4,   // Watermelon = 16
    // more items to be added
}

class Program
{
    static Dictionary<VNodeClassID, int> validation = new Dictionary<VNodeClassID, int>();
    static void Main(string[] args)
    {
        //{     D      A=1    O=2    G=4    B=8    W=16
        //    { false, true,  true,  false, true,  true },  
        //    { false, false, true,  true,  false, true }, 
        //    { false, true,  true,  false, true,  true }, 
        //    { false, true,  false, true,  true,  false },
        //    { false, true,  true,  true,  false, true },
        //    { false, false, true,  false, true,  true }
        //};
        // set like this
        MakeCompatibe(VNodeClassID.Watermellon,VNodeClassID.Orange|VNodeClassID.BlueBerry|VNodeClassID.Watermellon);
        // or
        validation[VNodeClassID.Default] = 1 + 2 + 8 + 16;
        validation[VNodeClassID.Apple] = 2 + 4 + 16;
        validation[VNodeClassID.Orange] = 1 + 2 + 8 + 16;
        validation[VNodeClassID.Grape] = 1 + 4 + 8;
        validation[VNodeClassID.BlueBerry] = 1 + 2 + 4 + 16;
        validation[VNodeClassID.Watermellon] = 2 + 8 + 16;


        Debug.Assert(CheckCompatibe(VNodeClassID.Apple, VNodeClassID.Watermellon));
        Debug.Assert(!CheckCompatibe(VNodeClassID.Default, VNodeClassID.Grape));
    }

    static void MakeCompatibe(VNodeClassID item, params VNodeClassID[] items)
    {
        int sum = items.Sum((v) => (int)v);
        validation[item] = sum;
    }

    static bool CheckCompatibe(VNodeClassID item, VNodeClassID other)
    {
        if (validation.ContainsKey(item))
        {
            int sum = validation[item];
            return (sum & (int)other) > 0;
        }
        return false;
    }
}

它是如何工作的?记住二进制系统。 enum中的每个项目代表不同值的bit。组合时,它们会创建一个数字,例如27.要检查是否在27中设置了8位,请执行AND操作并查看结果是否为非零。

27 : 00011011
 8 : 00001000  AND
-------------
   : 00001000  CHECK

答案 3 :(得分:0)

类似

Dictionary<<Tuple<VNodeClassID,VNodeClassID>,bool>>

可能是更好的类型安全和语义正确的方法。 例如:

   public class ValidKey: Tuple<VNodeClassID, VNodeClassID>
    {
        public ValidKey(VNodeClassID a, VNodeClassID b) : base(a, b) { }
    }


        static Dictionary<ValidKey, bool> validation = new Dictionary<ValidKey, bool>() {
            { new ValidKey(VNodeClassID.Apple, VNodeClassID.Watermellon), true },
            { new ValidKey(VNodeClassID.Apple, VNodeClassID.Orange), true },
            { new ValidKey(VNodeClassID.Orange, VNodeClassID.Grape), true }
        };
        bool Validate(VNodeClassID thing1, VNodeClassID thing2)
        {
            var key = new ValidKey(thing1, thing2);
            return validation.ContainsKey(key) ? validation[key] : false;
        }

用法:

   bool a = Validate(VNodeClassID.Apple, VNodeClassID.Watermellon);
   bool b = Validate(VNodeClassID.Grape, VNodeClassID.BlueBerry);