首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >按字符串设置枚举标志(按任何顺序)

按字符串设置枚举标志(按任何顺序)
EN

Code Review用户
提问于 2016-10-20 08:21:02
回答 3查看 3.6K关注 0票数 4

我希望设置以任何顺序以字符串表示形式给出的标志。这很吓人,因为你必须在我的演讲中检查2^3的可能选项。我只是想知道有什么比简单的蛮力更好的方法吗?任何优化和可读性改进都将是很棒的。这是我的密码:

代码语言:javascript
复制
[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;
}
}
EN

回答 3

Code Review用户

回答已采纳

发布于 2016-10-20 08:25:07

这是我对你代码的看法

代码语言:javascript
复制
[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()

票数 3
EN

Code Review用户

发布于 2016-10-20 08:29:54

在开始处理这些特性之前,最好先从字符串中提取薪资特性。你应该把这个放进方法(扩展?)专门研究这个的。

代码语言:javascript
复制
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扩展构建标志:

代码语言:javascript
复制
var salaryFeatures = fieldNames.Aggregate(SalaryFeatures.None, (result, next) 
    => result |= (SalaryFeatures)Enum.Parse(typeof(SalaryFeatures), next, true));
  • 使用Aggregate扩展连接这些标志
  • 使用ignoreCase = true
  • 实际上,salaryFeatures应该用PascalCase SalaryFeatures命名。
  • 如果您定义了另外一个标志None,您可以使用它而不是(salaryFeatures)0

这两个更改将允许您在不修改这些方法的情况下在将来添加更多标志。

票数 3
EN

Code Review用户

发布于 2016-10-23 10:21:58

下面是使用聚合扩展方法的另一个变体:

https://dotnetfiddle.net/7RrGTE

代码语言:javascript
复制
[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的存在)

票数 1
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/144738

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档