枚举超出范围

本文关键字:范围 枚举 | 更新日期: 2023-09-27 18:29:49

在我的测试函数中处理无效枚举的最佳方法是什么。该功能的设计允许我比较两个项目是否相互兼容。理想情况下,如果索引超出范围,我希望返回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);            
        }

枚举超出范围

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

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);            
}

您可以这样做:

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];

我建议使用[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

类似的东西

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);