C# 将字符串属性限制为预定义的值集(解决枚举中无连字符的问题)

C# 将字符串属性限制为预定义的值集(解决枚举中无连字符的问题),c#,enums,C#,Enums,我有一个字符串属性,我希望能够使用它强制执行两件事情: -只能将其设置为预定义列表中的特定值, -可以在编译时执行属性值的错误检查 枚举完全符合这一要求,只是在我的预定义字符串列表中有一个带有连字符和。为了说明枚举可以包含连字符的理想解决方案,我将创建以下枚举: public enum SIPEventPackagesEnum { dialog, message-summary, refer } 使用: SIPEventPackagesEnum EventPackage

我有一个字符串属性,我希望能够使用它强制执行两件事情: -只能将其设置为预定义列表中的特定值, -可以在编译时执行属性值的错误检查

枚举完全符合这一要求,只是在我的预定义字符串列表中有一个带有连字符和。为了说明枚举可以包含连字符的理想解决方案,我将创建以下枚举:

public enum SIPEventPackagesEnum
{
    dialog,
    message-summary,
    refer
}
使用:

SIPEventPackagesEnum EventPackage = SIPEventPackagesEnum.message-summary;
设置:

string eventPackageStr = "message-summary";
SIPEventPackagesEnum EventPackage = (SIPEventPackagesEnum)Enum.Parse(typeof(SIPEventPackagesEnum), eventPackageStr, true);
在上述情况下,除了一个枚举值之外,无法将EventPackage属性设置为任何值,而且使用起来很直观,因为intellisense将列出可用的选项

由于无法使用连字符,并且我无法更改预定义列表以删除连字符,因此非常粗糙的方法是使用一个结构,并在该结构上具有一个“Value”属性,该属性在其setter中执行强制,请参见下文。与使用枚举相比,它非常冗长,而且不允许任何编译时检查,也不太直观

以前是否有人遇到过此问题,并有更好的解决方案?我有多个包含连字符的列表,所以这不是一次性的

public struct SIPEventPackages
{
    public const string DIALOG = "dialog";                   
    public const string MESSAGE_SUMMARY = "message-summary";   
    public const string REFER = "refer";                      

    public string Value
    {
        get { return Value; }
        set
        {
            if (IsValid(value))
            {
                Value = value.ToLower();
            }
            else
            {
                throw new ArgumentException(value + " is invalid for a SIP event package.");
            }
        }
    }

    public bool IsValid(string value)
    {
        if (value.IsNullOrBlank())
        {
            return false;
        }
        else if (value.ToLower() == DIALOG || value.ToLower() == MESSAGE_SUMMARY || value.ToLower() == REFER)
        {
            return true;
        }
        else
        {
            return false;
        }
    }

    public override string ToString()
    {
        return Value;
    }
}

使用委托似乎很简单

        Func<string, bool> isValid = str =>
        {
            List<string> validLst = new List<string>() { "dialog","message-summary","refer" };
            if (validLst.Find(x => string.Equals(x,str,StringComparison.InvariantCultureIgnoreCase)) == null)
                return false;
            return true;

        };

        var teststr1 = "message-summary";
        var teststr2 = "wrongone";
        isValid(teststr1);
        isValid(teststr2);

使用委托似乎很简单

        Func<string, bool> isValid = str =>
        {
            List<string> validLst = new List<string>() { "dialog","message-summary","refer" };
            if (validLst.Find(x => string.Equals(x,str,StringComparison.InvariantCultureIgnoreCase)) == null)
                return false;
            return true;

        };

        var teststr1 = "message-summary";
        var teststr2 = "wrongone";
        isValid(teststr1);
        isValid(teststr2);

您可以在不使用-的情况下创建枚举,然后在从枚举值映射到字符串的帮助器类中创建一个静态
字典
,以从枚举转换到字符串,然后在从字符串转换到枚举时使用
enum.Parse(typeof(SIPEventPackagesEnum),str.Replace(“-”,”)

或使用uu代替-并在需要时用-替换uu,反之亦然


或者在枚举值中使用驼峰大小写,并使用正则表达式将枚举名称中的大写字母替换为“-”,您可以在不使用“-”的情况下创建枚举,然后在帮助器类中创建一个从枚举值映射到字符串的静态
字典,以从枚举转换为字符串,然后使用
enum.Parse(typeof(SIPEventPackagesEnum),str.Replace(“-”和“”)
从字符串转换为枚举时

或使用uu代替-并在需要时用-替换uu,反之亦然


或者在枚举值中使用驼峰大小写,并使用正则表达式将枚举名称中的大写字母替换为“-”,我成功地调整了我的方法,使其几乎与枚举一样好,尽管需要更多的管道代码。这是值得的管道代码,以节省潜在的误用问题在未来

public struct SIPEventPackage
{
    public static SIPEventPackage None = new SIPEventPackage(null);
    public static SIPEventPackage Dialog = new SIPEventPackage("dialog");                   
    public static SIPEventPackage MessageSummary = new SIPEventPackage("message-summary"); 
    public static SIPEventPackage Refer = new SIPEventPackage("refer");                    

    private string m_value;

    private SIPEventPackage(string value)
    {
        m_value = value;
    }

    public override string ToString()
    {
        return m_value;
    }

    public static SIPEventPackage Parse(string value)
    {
        if (!IsValid(value))
        {
            throw new ArgumentException("The value is not valid for a SIPEventPackage.");
        }
        else
        {
            string trimmedValue = value.Trim().ToLower();
            switch (trimmedValue)
            {
                case "dialog": return SIPEventPackage.Dialog;
                case "message-summary": return SIPEventPackage.MessageSummary;
                case "refer": return SIPEventPackage.Refer;
                default: throw new ArgumentException("The value is not valid for a SIPEventPackage.");
            }
        }
    }
}

需要更多的管道,实现一个IsValid方法和操作符==等等,但最重要的是,我现在可以以与枚举几乎相同的方式使用结构,并且可以使用带有连字符的项。

我成功地调整了我的方法,使其几乎与枚举一样好,尽管需要更多的管道代码。这是值得的管道代码,以节省潜在的误用问题在未来

public struct SIPEventPackage
{
    public static SIPEventPackage None = new SIPEventPackage(null);
    public static SIPEventPackage Dialog = new SIPEventPackage("dialog");                   
    public static SIPEventPackage MessageSummary = new SIPEventPackage("message-summary"); 
    public static SIPEventPackage Refer = new SIPEventPackage("refer");                    

    private string m_value;

    private SIPEventPackage(string value)
    {
        m_value = value;
    }

    public override string ToString()
    {
        return m_value;
    }

    public static SIPEventPackage Parse(string value)
    {
        if (!IsValid(value))
        {
            throw new ArgumentException("The value is not valid for a SIPEventPackage.");
        }
        else
        {
            string trimmedValue = value.Trim().ToLower();
            switch (trimmedValue)
            {
                case "dialog": return SIPEventPackage.Dialog;
                case "message-summary": return SIPEventPackage.MessageSummary;
                case "refer": return SIPEventPackage.Refer;
                default: throw new ArgumentException("The value is not valid for a SIPEventPackage.");
            }
        }
    }
}

实现IsValid方法和运算符==以及其他一些方法需要更多的管道,但主要的是我现在可以以与枚举几乎相同的方式使用结构,并且可以使用带有连字符的项。

这将是正确的方法,除了不能在枚举上重写ToString()。因此,当我需要将枚举值(在本例中是写入XML文档)时,很容易错过转换。这是正确的方法,但不能覆盖枚举上的ToString()。因此,当我需要将枚举值写入XML文档时,很容易错过转换。