将方法参数中的枚举类型限制为用户定义的枚举

Constrain enum type in method parameter to user defined enum(s)

我在我的自定义命名空间中自己的 .cs 文件中有少量固定数量的枚举。大多数枚举名称是我的 SQLite 数据库中相应 table 名称的前缀。因此,每个枚举中的 string 和 int 值分别是 name 和 id 的记录值,因此允许我轻松跟踪在执行 SQL 查询的方法中传递哪些数据。

public enum TableNamePrefix //respective table name would be "TableNamePrefix_SomeNameHere"
    {
        value1 = 1, //name = "value1", id = 1
        value2 = 2, //name = "value2", id = 2
        //...
    }

public enum TableNamePrefix2
    {
        //...
    }

//...

目标是在我进行查询时简化我的数据库搜索条件,这将大大限制接收空记录的机会。这是我用来 return 一个 table 行的方法之一。

public static T GetTableRow(DBTableNameAbberviations tableNameAbb, Enum prefix,
            string keyword = "", string name = "") //tableNameAbb is another enum

上面的方法按预期工作,但我不想 Enum prefix 允许传入任何 Enum,这让我想到了我的问题。有没有办法将其限制为单个或多个用户定义的枚举?换句话说,不是将任何通用枚举传递给我的第二个参数,而是有办法将其限制为 TableNamePrefix 和我其他省略的枚举吗?如果没有,那么解决方法是什么?

我考虑过使用带有约束的通用方法,但 where T2: System.Enum 仍然允许使用任何 Enum

限制类型很困难(除非它是泛型类型),您可以做的是在枚举的方法上创建一个类型参数并将其限制为枚举类型:

... GetTableRow<TEnum>(... TEnum prefix, ...) : where TEnum : EnumType {}

,或者如果 enum 不是您想要的类型则抛出异常。

您可以考虑使用类型安全的枚举,因为您似乎有额外的数据想要伴随您的枚举。

这是我们将用于类型安全枚举的基础 class。它提供了所有类型安全枚举、值和名称的基础知识。

 public abstract class TypeSafeEnumBase<TValue>
    {
        public readonly TValue Value;
        public readonly string Name;

        protected TypeSafeEnumBase(TValue value, string name)
        {
            this.Value = value;
            this.Name = name;            
        }

        public override string ToString()
        {
            return Name;
        }

        private static TypeSafeEnumBase<TValue>[] Items { get; set; }

        public static IEnumerable<TypeSafeEnumBase<TValue>> GetValues<TType>()
        {
            if (Items == null || Items.Length == 0)
            {
                Dictionary<string, TType> items = typeof(TType)
                    .GetFields(BindingFlags.Public | BindingFlags.Static)
                    .Where(f => f.FieldType == typeof(TType))
                    .ToDictionary(f => f.Name,
                        f => (TType)f.GetValue(null));
                Items = items.Values.Cast<TypeSafeEnumBase<TValue>>().ToArray();
            }

            foreach (TypeSafeEnumBase<TValue> item in Items)
            {
                yield return item;
            }
        }
    }

这是您的 'table details' 类型安全枚举设置。在此 class 中,我们实现了可能需要的任何其他属性,例如前缀、关键字等

public sealed class TableDetails : TypeSafeEnumBase<int>
    {
        public static TableDetails TableOneDetails = new TableDetails(1, "value1", "TableNamePrefix1","table1keyword");
        public static TableDetails TableTwoDetails = new TableDetails(2, "value2","TableNamePrefix2", "table2keyword");
        public static TableDetails TableThreeDetails = new TableDetails(3, "value3", "TableNamePrefix3", "table3keyword");

        public TableDetails(int value, string name, string prefix, string keyword) : base(value, name)
        {
            Prefix = prefix;
            Keyword = keyword;
        }

        public string Prefix { get; }
        public string Keyword { get; }

        public static bool TryParse(int value, out TableDetails tableDetails)
        {
            return TryParse(value.ToString(), out tableDetails);
        }

        public static bool TryParse(string value, out TableDetails tableDetails)
        {
            try
            {
                tableDetails= Parse(value);
                return true;
            }
            catch
            {
                tableDetails= null;
                return false;
            }
        }

        public static TableDetails Parse(int value)
        {
            return Parse(value.ToString());
        }

        public static TableDetails Parse(string value)
        {
            switch (value)
            {
                case "1":
                case nameof(TableOneDetails):
                    return TableOneDetails;
                case "2":
                case nameof(TableTwoDetails):
                    return TableTwoDetails;
                case "3":
                case nameof(TableThreeDetails):
                    return TableThreeDetails;                
                default:                    
                    throw new IndexOutOfRangeException($"{nameof(TableDetails)} doesn't contain {value}.");
            }
        }

        public override string ToString()
        {
            return base.Name;
        }
    }

您现在可以更改 GetTableRow 方法以接受类型 TableDetails。此外,您只有一个参数要传递,即 TableDetails,如果您需要添加更多参数,您可以更新 TableDetails 对象,而无需更改 GetTableRow 方法签名。

public static T GetTableRow(TableDetails tableDetails)