我从远程设备获取数据,该设备发送包含单字母代码的状态字符串的数字数据。 我需要将字符串中的所有单字符状态代码映射到相应的枚举值,并将这些枚举值放入属性中,然后类消费者可以调用该属性来理解状态,而无需查找单字符状态代码。示例状态字符串是“... Q.D..B”。
是否有一种模式可以在不使用巨大的switch语句或多个if语句的情况下执行此操作?
注意:代码实际上包含了20多种状态,但为了简洁起见,我已对其进行了编辑。
[Flags]
public enum DataQuality
{
Good = 0x0001,
Questionable = 0x0004,
NotCorrected = 0x0008,
BadEstimatedValue = 0x0010
}
public class DataPointStatus
{
private const string Good = "...";
private const char Questionable = 'Q';
private const char NotCorrected = 'D';
private const char BadEstimatedValue = 'B';
// Lot's more statuses...
private readonly string _rawStatus;
private readonly List<DataQuality> _statuses = new List<DataQuality>();
public DataPointStatus(string rawStatus)
{
if (rawStatus == null)
{
throw new ArgumentNullException($"'{nameof(rawStatus)}' cannot be null.");
}
if (rawStatus.Trim() == string.Empty)
{
throw new ArgumentException($"'{nameof(rawStatus)}' cannot be an empty string.");
}
_rawStatus = rawStatus;
SetStatusToGoodIfDataHasNoQualityErrors();
if (!IsGood) SetBadQualityStatuses();
}
public bool IsGood => _statuses.Any(x => x == DataQuality.Good);
public IEnumerable<DataQuality> Statuses => _statuses;
private void CheckForGoodStatus()
{
if (_rawStatus == Good)
{
_statuses.Add(DataQuality.Good);
}
}
private void SetStatusToGoodIfDataHasNoQualityErrors()
{
string status = _rawStatus.Replace(".", string.Empty);
Start:
switch (status)
{
case string s when s == "": return;
case string s when s.Contains(Questionable):
_statuses.Add(DataQuality.Questionable);
status = status.Trim(Questionable);
goto Start;
case string s when s.Contains(NotCorrected):
_statuses.Add(DataQuality.NotCorrected);
status = status.Trim(NotCorrected);
goto Start;
case string s when s.Contains(BadEstimatedValue):
_statuses.Add(DataQuality.BadEstimatedValue);
status = status.Trim(BadEstimatedValue);
goto Start;
default:
throw new ArgumentOutOfRangeException(
$"Invalid status code.");
}
}
}
答案 0 :(得分:1)
您可以将枚举存储在字典中:
var dic = new Dictionary<string, DataQuality>(StringComparer.OrdinalIgnoreCase)
{
["G"] = DataQuality.Good,
["Q"] = DataQuality.Questionable,
["N"] = DataQuality.NotCorrected,
["B"] = DataQuality.BadEstimatedValue
};
string input = "Q";
if (dic.TryGetValue(input, out var status))
{
// Use "status" variable here
}
答案 1 :(得分:1)
您可以使用正则表达式查找状态
//Regular expression can be more elaborated,
//searching the status char in a concrete part of the string and so on
Regex regex = new Regex("Q|D|B");
然后是一个字典,用于将字符串值与相应的标记值
相匹配Dictionary<string, DataQuality> qualities = InitializeDictionary();
这可以放在一个循环中。类似于while (rawStatus != "")
:
Match match = regex.Match(rawStatus);
if (match.Success) {
_statuses.Add(qualities[match.Value]);
rawStatus = regex.Replace(rawStatus, "");
}
答案 2 :(得分:1)
这不会直接适用于您的代码,因为您需要旗帜 要将字符串解析为枚举值列表,可以使用char枚举:
Enum MyEnum
{
Good = 'g',
Questionable = 'q',
NotCorrected = 'n',
BadEstimatedValue = 'b'
//[...]
}
您可以使用Enum.TryParse或Parse将字符串转换为其枚举值
但对于一个char来说,需要一个简单的演员(MyEnum)myChar
这会将所有char转换为int值,即使它们未在枚举中定义
Enum.IsDefined将指示它是否存在于指定的枚举中。
对于char enum:
var input = "qngb###qnga";
var result = input.Where(x => Enum.IsDefined(typeof(toto), (int)x))
.Select(x => (toto)x);
结果:
可疑
NotCorrected
好
BadEstimatedValue
可疑
NotCorrected
好