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文档时,很容易错过转换。