如何将变量限制为一组固定的字符串
本文关键字:一组 字符串 变量 | 更新日期: 2023-09-27 18:27:48
如果我想将数据库中spiselevel列的值限制为1、2和3,我可以执行类似的操作
private enum SpiceLevel
{
Low=1,
Medium=2,
Hot=3
}
然后在代码中,我可以使用(int)SpiceLevel.Low
来选择1作为香料级别。
现在,如果我有一个需求,我只能接受"红玫瑰"、"白玫瑰"answers"黑玫瑰"作为数据库中列的值,该怎么办?处理这个问题的优雅方法是什么?
我正在考虑将它们存储在配置文件或常量中,但两者都不如枚举那样优雅。有什么想法吗?
更新:
这里的答案对我有效
您可以将property
用于此
public string[] AllowedRoses = new string[] { "Red Rose", "White Rose" ,"Black Rose" };
string _Rose = "Red Rose";
public string Rose
{
get
{
return _Rose;
}
set
{
if (!AllowedRoses.Any(x => x == value))
throw new ArgumentException("Not valid rose");
_Rose = value;
}
}
我可以看到以下选项:
-
验证setter中的值(例如参见l4V的答案)
-
从概念上讲,您正在考虑枚举。因此,您可以执行以下操作:
enum RoseType { RedRose, WhiteRose, BlackRose };
然后提供从该枚举到字符串的适当转换。这里描述了两个方便的选项:使用用户友好字符串的EnumToString。一个是使用自定义的Description属性,第二个(我更喜欢这个)提供一个扩展方法:
public static class RoseTypeExtensions { public static string GetString(this RoseType @this) { switch (@this) { case RoseType.RedRose: return "Red Rose"; case RoseType.WhiteRose: return "White Rose"; case RoseType.BlackRose: return "Black Rose"; default: throw new InvalidOperationException(); } } }
- 创建一组常量:
public class RoseType { public readonly RoseType RedRose = new RoseType("Red Rose"); public readonly RoseType WhiteRose = new RoseType("White Rose"); public readonly RoseType BlackRose = new RoseType("Black Rose"); public string Content { get; private set; } private RoseType(string content) { this.Content = content; } public override string ToString() { return this.Content; } }
正如Oskar Berggren在评论中正确指出的那样,RoseType
还应在ToString
之外提供其他标准覆盖:Equals
、GetHashCode
、operator==
和operator!=
。
没有真正好的解决方案。所有这些都要求数据库与C#中的枚举"同步"。
最简单的解决方案:
您所说的将枚举值作为整数存储在数据库中。
几乎同样简单但效率较低:
将值作为字符串存储在数据库中,并使用anEnumVar.ToString()
和Enum.Parse
(或enum中的任何其他解析方法)在字符串和枚举之间进行转换。
复杂但灵活:
在数据库中有一种枚举:一个包含字符串值和id的表,然后使用外键保存枚举。这允许您使用数值或字符串值(通过联接)选择/更新/插入。
它还保持完整性,因为不可能存储没有相应枚举值的整数。
缺点是复杂性。
使用Dictionary<string, SpiceLevel>
创建字符串到枚举的映射,以将字符串与枚举相关联。把它们包在一个班级里。
您也可以使用Decorator属性[Name("Red Rose"] Low=1,
并从枚举本身获取该属性,但这涉及到反射,这会带来一些性能问题,尤其是在遍历枚举值以找到具有匹配属性的值时。
public static class Spice
{
public enum Level
{
Low = 1,
Medium = 2,
Hot = 3
}
private static readonly Dictionary<string, Level> spices = new Dictionary<string, Level>{
{ "Red Rose", Level.Low },
{ "White Rose", Level.Medium },
{ "Black Rose", Level.Hot },
};
public static bool TryGet(string spiceName, out Level spiceLevel) => spices.TryGetValue(spiceName, out spiceLevel);
public static string SpiceName(Level target) => Enum.GetName(typeof(Spice.Level), target);
}
/// <summary>
/// Some tests to validate it works. This could be a unit test or just in a console app
/// </summary>
public class SpiceTest
{
public void VerifyBlackRoseIsHot()
{
string subject = "Black Rose";
Spice.Level expectedSpice;
// Here's the ease of use. Pass a string, get an enum and whether it's a valid string
var result = Spice.TryGet(subject, out expectedSpice);
//Some Assertion from a unit test library
Assert.True(result, $"Unable to find spice '{subject}', when it should exist");
Assert.True(Spice.Level.Hot.Equals(expectedSpice), $"The returned spice '{ Spice.SpiceName(expectedSpice) }' was not the value 'Hot' as expected");
}
}