我希望设置以任何顺序以字符串表示形式给出的标志。这很吓人,因为你必须在我的演讲中检查2^3的可能选项。我只是想知道有什么比简单的蛮力更好的方法吗?任何优化和可读性改进都将是很棒的。这是我的密码:
[Flags]
public enum salaryFeatures
{
Children = 1,
Graduate = 2,
Disability = 4
}
class Program
{
public static void Main()
{
string Employee = "10023 Mark Male 6.7 70 30 20 Children Graduate";
salaryFeatures f;
f = GetFeaturesByString(Employee);
}
public static salaryFeatures GetFeaturesByString(string fields)
{
bool children = false;
bool graduate = false;
bool disability = false;
salaryFeatures features = new salaryFeatures();
if (fields.ToLower().Contains("children")) children = true;
if (fields.ToLower().Contains("graduate")) graduate = true;
if (fields.ToLower().Contains("disability")) disability = true;
if (children && graduate && disability)
{
return features = salaryFeatures.Children | salaryFeatures.Disability | salaryFeatures.Graduate;
}
if (children && graduate)
{
return features = salaryFeatures.Children | salaryFeatures.Graduate;
}
if (children && disability)
{
return features = salaryFeatures.Children | salaryFeatures.Disability;
}
if (children)
{
return features = salaryFeatures.Children;
}
if (graduate && disability)
{
return features = salaryFeatures.Graduate | salaryFeatures.Disability;
}
if (graduate)
{
return features = salaryFeatures.Graduate;
}
if (disability)
{
return features = salaryFeatures.Disability;
}
return features;
}
}发布于 2016-10-20 08:25:07
这是我对你代码的看法
[Flags]
public enum SalaryFeatures
{
None= 0,
Children = 1,
Graduate = 2,
Disability = 4
}
class Program
{
public static void Main()
{
string Employee = "10023 Mark Male 6.7 70 30 20 Children Graduate";
SalaryFeatures f;
f = GetFeaturesByString(Employee);
// f.Dump(); //LinqPad only
}
public static SalaryFeatures GetFeaturesByString(string fields)
{
SalaryFeatures features = SalaryFeatures.None;
if (fields.IndexOf("children", StringComparison.OrdinalIgnoreCase) >= 0) features |= SalaryFeatures.Children;
if (fields.IndexOf("graduate", StringComparison.OrdinalIgnoreCase) >= 0) features |= SalaryFeatures.Graduate;
if (fields.IndexOf("disability", StringComparison.OrdinalIgnoreCase) >= 0) features |= SalaryFeatures.Disability;
return features;
}
}首先,枚举的定义不完整。您需要为它定义一个无值。
使用None作为值为零的枚举常量标志的名称。不能在按位和操作中使用None枚举常量来测试标志,因为结果总是为零。但是,可以在数值和None枚举常量之间执行逻辑比较,而不是按位进行比较,以确定是否设置了数值中的任何位。
在定义标志枚举时,也请参见指导方针。我还将枚举的命名更改为PascalCase (SalaryFeatures)。
在此之后,我改进了方法GetFeaturesByString,使其使用按位或组合值,具体取决于字符串中的值。我还使用IndexOf(string, StringComparison)方法来检查源字符串中是否存在搜索字符串,而不是使用ToLower()和Contains()。
发布于 2016-10-20 08:29:54
在开始处理这些特性之前,最好先从字符串中提取薪资特性。你应该把这个放进方法(扩展?)专门研究这个的。
var text = "10023 Mark Male 6.7 70 30 20 Children Graduate";
var fieldNames = Enum.GetNames(typeof(salaryFeatures)).Where(n => text.IndexOf(n) >= 0);现在,在找到字段之后,您可以在另一个方法中解析它们,忽略该情况,并使用linq的Aggregate扩展构建标志:
var salaryFeatures = fieldNames.Aggregate(SalaryFeatures.None, (result, next)
=> result |= (SalaryFeatures)Enum.Parse(typeof(SalaryFeatures), next, true));Aggregate扩展连接这些标志ignoreCase = truesalaryFeatures应该用PascalCase SalaryFeatures命名。None,您可以使用它而不是(salaryFeatures)0。这两个更改将允许您在不修改这些方法的情况下在将来添加更多标志。
发布于 2016-10-23 10:21:58
下面是使用聚合扩展方法的另一个变体:
https://dotnetfiddle.net/7RrGTE
[Flags]
public enum SalaryFeatures
{
None = 0,
Children = 1,
Graduate = 2,
Disability = 4
}
//...
var employee = "Mark: Disability Male with Children";
var features =
Enumerable.
Range(0, Enum.GetValues(typeof(SalaryFeatures)).Length - 1).
Aggregate
(
SalaryFeatures.None,
(f, b) =>
employee.
Contains(
((SalaryFeatures)(1 << b)).
ToString()) ?
f | (SalaryFeatures)(1 << b)
:
f
);
var f = (int)features;
Console.WriteLine(f); // expected: 5(其中"Length - 1“说明SalaryFeatures.None的存在)
https://codereview.stackexchange.com/questions/144738
复制相似问题