C# 精简switch语句

C# 精简switch语句,c#,switch-statement,C#,Switch Statement,想知道是否有好的替代方案,它的性能不比我下面介绍的差?real switch语句有其他非英语字符的附加部分 请注意,我希望每行放置多个case语句,但StyleCop不喜欢它,因此将导致我们的发布版本失败 var retVal = String.Empty; switch(valToCheck) { case "é": case "ê": case "è":

想知道是否有好的替代方案,它的性能不比我下面介绍的差?real switch语句有其他非英语字符的附加部分

请注意,我希望每行放置多个case语句,但StyleCop不喜欢它,因此将导致我们的发布版本失败

        var retVal = String.Empty;
        switch(valToCheck)
        {
            case "é": 
            case "ê": 
            case "è": 
            case "ë":
                retVal = "e";
                break;
            case "à": 
            case "â": 
            case "ä": 
            case "å":
                retVal = "a";
                break;

            default:
                retVal = "-";
                break;
        }

首先想到的是一本
字典()
(我更喜欢char而不是string,因为您正在处理char)


首先想到的是一本
字典()
(我更喜欢char而不是string,因为您正在处理char)


好吧,从这个转换开始

public class CharacterSanitizer
{
    private static Dictionary<string, string> characterMappings = new Dictionary<string, string>();
    static CharacterSanitizer()
    {
        characterMappings.Add("é", "e");
        characterMappings.Add("ê", "e");
        //...
    }

    public static string mapCharacter(string input)
    {
        string output;
        if (characterMappings.TryGetValue(input, out output))
        {
            return output;
        }
        else
        {
            return input;
        }
    }
}
公共类字符消毒剂
{
私有静态字典characterMappings=新字典();
静态字符消毒剂()
{
字符映射。添加(“e”、“e”);
字符映射。添加(“ê”、“e”);
//...
}
公共静态字符串映射字符(字符串输入)
{
字符串输出;
if(characterMappings.TryGetValue(输入、输出))
{
返回输出;
}
其他的
{
返回输入;
}
}
}

现在,角色映射是数据的一部分,而不是代码的一部分。我已经在这里硬编码了这些值,但现在将映射存储在一个文件中,读入该文件,然后相应地填充字典就足够简单了。通过这种方式,您不仅可以通过将case语句缩减为一位文本文件(代码之外)来大量清理代码,而且还可以在不需要重新编译的情况下对其进行修改。

好的,从执行此转换开始

public class CharacterSanitizer
{
    private static Dictionary<string, string> characterMappings = new Dictionary<string, string>();
    static CharacterSanitizer()
    {
        characterMappings.Add("é", "e");
        characterMappings.Add("ê", "e");
        //...
    }

    public static string mapCharacter(string input)
    {
        string output;
        if (characterMappings.TryGetValue(input, out output))
        {
            return output;
        }
        else
        {
            return input;
        }
    }
}
公共类字符消毒剂
{
私有静态字典characterMappings=新字典();
静态字符消毒剂()
{
字符映射。添加(“e”、“e”);
字符映射。添加(“ê”、“e”);
//...
}
公共静态字符串映射字符(字符串输入)
{
字符串输出;
if(characterMappings.TryGetValue(输入、输出))
{
返回输出;
}
其他的
{
返回输入;
}
}
}

现在,角色映射是数据的一部分,而不是代码的一部分。我已经在这里硬编码了这些值,但现在将映射存储在一个文件中,读入该文件,然后相应地填充字典就足够简单了。通过这种方式,您不仅可以通过将case语句缩减为一位文本文件(代码之外)来大量清理代码,还可以在不需要重新编译的情况下对其进行修改。

您可以进行小范围检查并查看ascii值

假设
InRange(val,min,max)
检查数字是否在范围内

if(InRange(System.Convert.ToInt32(valToCheck),232,235))
  return 'e';
else if(InRange(System.Convert.ToInt32(valToCheck),224,229))
  return 'a';

<>这使得代码有点混乱,取决于所使用的标准,但可能需要考虑的事情。

< p>您可以进行一个小范围检查并查看<强> ASCII值>/P> 假设
InRange(val,min,max)
检查数字是否在范围内

if(InRange(System.Convert.ToInt32(valToCheck),232,235))
  return 'e';
else if(InRange(System.Convert.ToInt32(valToCheck),224,229))
  return 'a';

<>这使得代码有点混乱,取决于所使用的标准,但可能要考虑的事项。

< p>使用<代码>包含< /代码>而不是<代码>开关< /代码> .<
var retVal = String.Empty;

string es = "éêèë";
if (es.Contains(valToCheck)) retVal  = "e";
//etc.

使用
包含
而不是
开关

var retVal = String.Empty;

string es = "éêèë";
if (es.Contains(valToCheck)) retVal  = "e";
//etc.

这个答案假定您将把switch语句应用于字符串,而不仅仅是单个字符(尽管这样也可以)

最好的方法似乎是中概述的方法

我将其调整为使用LINQ:

var chars = from character in valToCheck.Normalize(NormalizationForm.FormD)
            where CharUnicodeInfo.GetUnicodeCategory(character)
                    != UnicodeCategory.NonSpacingMark
            select character;
return string.Join("", chars).Normalize(NormalizationForm.FormC);
您需要
System.Globalization的using指令

样本输入:

样本输出:


这个答案假定您将把switch语句应用于字符串,而不仅仅是单个字符(尽管这样也可以)

最好的方法似乎是中概述的方法

我将其调整为使用LINQ:

var chars = from character in valToCheck.Normalize(NormalizationForm.FormD)
            where CharUnicodeInfo.GetUnicodeCategory(character)
                    != UnicodeCategory.NonSpacingMark
            select character;
return string.Join("", chars).Normalize(NormalizationForm.FormC);
您需要
System.Globalization的using指令

样本输入:

样本输出:


基于Michael Kaplan的RemoveDiacritics(),您可以执行以下操作:

static char RemoveDiacritics(char c)
{
    string stFormD = c.ToString().Normalize(NormalizationForm.FormD);
    StringBuilder sb = new StringBuilder();

    for (int ich = 0; ich < stFormD.Length; ich++)
    {
        UnicodeCategory uc = CharUnicodeInfo.GetUnicodeCategory(stFormD[ich]);
        if (uc != UnicodeCategory.NonSpacingMark)
        {
            sb.Append(stFormD[ich]);
        }
    }

    return (sb.ToString()[0]);
}

switch(RemoveDiacritics(valToCheck))
{
    case 'e':
        //...
        break;
    case 'a':
        //...
        break;
        //...
}

基于Michael Kaplan的RemoveDiacritics(),您可以执行以下操作:

static char RemoveDiacritics(char c)
{
    string stFormD = c.ToString().Normalize(NormalizationForm.FormD);
    StringBuilder sb = new StringBuilder();

    for (int ich = 0; ich < stFormD.Length; ich++)
    {
        UnicodeCategory uc = CharUnicodeInfo.GetUnicodeCategory(stFormD[ich]);
        if (uc != UnicodeCategory.NonSpacingMark)
        {
            sb.Append(stFormD[ich]);
        }
    }

    return (sb.ToString()[0]);
}

switch(RemoveDiacritics(valToCheck))
{
    case 'e':
        //...
        break;
    case 'a':
        //...
        break;
        //...
}


出于好奇,为什么默认的
“-”
?您可以构建一个查找表(使用可读性最高的方法,这可能会很慢)。查找非常简单,速度也非常快。@LittleBobbyTables:C#根本不支持这一点,IIRC。您可以直接返回结果,而不是设置
retval
(假设以后不使用)。@DaveShaw:感谢您的链接。出于好奇,为什么默认的
“-”
?您可以构建一个查找表(使用可读性最高的方法,可能会比较慢)。查找非常简单,速度也非常快。@LittleBobbyTables:C#根本不支持这一点,IIRC。您可以直接返回结果,而不是设置
retval
(假设以后不使用)@DaveShaw:谢谢你的链接。为了提高性能,请使用TryGetValue而不是ContainsKey。对于编译,请使用
字典而不是
字典。与其使用
==false
,不如使用NOT运算符(
)@TimCopenhaver要跟进Steve的评论,如果你打电话给ContainsKey,然后打电话给indexer,你会打电话给FindEntry两次。这类似于在真正的字典中查找一个单词是否在那里,如果在那里,关闭字典,打开它再次查找该单词,然后阅读定义。@Steve这就像添加
+0
*1
到数值计算的结尾。这是毫无意义的。而且
char retValue='';
可以是
char retValue;
为了性能,请使用TryGetValue而不是ContainsKey。对于编译,请使用
Dictionary
而不是
Dictionary
。而不是
==false
您应该