C#:如何在不使用 switch 的情况下为字符串 var 赋值

C#: how assign a value to a string var without using switch

首先我必须说我是 C# 的新手。我编写了这个代码块来根据另一个 var 的值为字符串 var 赋值。我使用了 Switch 语句:

    switch (_reader.GetString(0))
    {
       case "G":
            permiso.Area = "General";
            break;
       case "SIS":
            permiso.Area = "Sistems";
            break;
       case "SOP":
            permiso.Area = "Development";
            break;
       case "HLP":
            permiso.Area = "Support";
            break;
       }

我可以用 C# 更简单地实现吗? 谢谢!

您可以使用 Dictionary(),它可以将“switch case”字符串存储为键,将“switch case value”存储在值中。

示例:

var dict = new Dictionary<string, string>()
{
  {"G", "General"},
  {"SIS", "Sistems"},
  ...
}
So your code in order to access will be: 
var key = _reader.GetString(0);
if(dict.TryGetValue(key, out var value)
{
   permiso.Area = value;
}
else
{
  // handle not exists key situation
}

I mean if exists in C# somo sentence that makes something like that: my_string=my_string.decode(old_value0,new_value0, old_value1,new_value1, ...)

如果你想要像 Oracle 的 DECODE 这样的东西,你可以这样写:

string Decode(string expr, params string[] arr){

  for(int i = 0; i < arr.Length; i+=2)
    if(arr[i] == expr)
      return arr[i+1];
  return arr.Length % 2 == 0 ? null : arr[arr.Length-1];
}

你会像这样使用它:

permiso.Area = Decode(reader.GetString(0), "G", "General", "SIS", "Sistems", "SOP", "Development", "HLP", "Support");

如果你想要一个 ELSE,传递一个奇数长度的数组(“支持”之后的东西)

如果您希望能够在字符串上调用它,例如 reader.GetString(0).Decode("G" ...) 您可以在静态 class 中声明它并在第一个参数之前加上 this :

static string Decode(this string expr, ....)

这将使它成为一个扩展方法,因此可以“在字符串上”调用它

现代 C# 有一个模式匹配开关

permiso.Area = _reader.GetString(0) switch {
  "G" => "General",
  "SIS" => "Sistems",
  "SOP" => "Development",
  "HLP" => "Support",
  _ => throw new InvalidOperationException($"The value {_reader.GetString(0)} is not handled")
};

如果你不在末尾包含“else”,C# 会抱怨你_ =>

如果您在多个位置出现相同的映射,或者通常重复使用相同的字符串(例如,在某些情况下),则更复杂和更简洁的方法是首先使用枚举及其描述。这使代码更具可读性,因为您可以(并且应该)在代码中使用唯一枚举并在需要时捕获其描述。

您需要此枚举扩展方法来读取枚举描述:

using System;
using System.ComponentModel;

public static string Description(this Enum source) {
  DescriptionAttribute[] attributes = (DescriptionAttribute[])source
    .GetType()
    .GetField(source.ToString())
    .GetCustomAttributes(typeof(DescriptionAttribute), false);
  return attributes.Length > 0 ? attributes[0].Description : string.Empty;
}

准备枚举及其相应的字典映射器。如果可能,这些枚举应该只有 one 唯一描述,但您可以根据自己的喜好定义其他映射器字典,例如当您需要一个简单的短到长文本映射器时,如您的示例所示。

using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;

// enum and its description
public enum PermissionArea {
  [Description("Development")]
  Development = 1,
  [Description("General")]
  General,
  [Description("Sistems")]
  Sistems,
  [Description("Support")]
  Support
}

public static class MyEnumDicts {
  // default mapping of enum to its description
  public static readonly Dictionary<PermissionArea, string> PermissionAreaToText = new Dictionary<PermissionArea, string>() {
    { PermissionArea.Development, PermissionArea.Development.Description() },
    { PermissionArea.General,     PermissionArea.General.Description() },
    { PermissionArea.Sistems,     PermissionArea.Sistems.Description() },
    { PermissionArea.Support,     PermissionArea.Support.Description() }
  };

  // mapping of enum to short text
  // (only if needed as it is better to only use one unique
  // value which is already set as description in the enum itself
  public static readonly Dictionary<PermissionArea, string> PermissionAreaToShortText = new Dictionary<PermissionArea, string>() {
    { PermissionArea.Development, "SOP" },
    { PermissionArea.General,     "G" },
    { PermissionArea.Sistems,     "SIS" },
    { PermissionArea.Support,     "Support" }
  };

  // add reverse mappers via linq
  public static readonly Dictionary<string, PermissionArea> TextToPermissionArea      = PermissionAreaToText.ToDictionary(m => m.Value, m => m.Key);
  public static readonly Dictionary<string, PermissionArea> ShortTextToPermissionArea = PermissionAreaToShortText.ToDictionary(m => m.Value, m => m.Key);
}

用法如下:

public void MyMethod(string permissionAreaShortText) {
  try {
    // map to enum (no switch or ifs etc. needed here)
    PermissionArea permissionArea = MyEnumDicts.ShortTextToPermissionArea[permissionAreaShortText];

    // now you can work via enums and do not
    // have to hassle with any strings anymore:
    switch (permissionArea) {
      case PermissionArea.Development: ...; break;
      case PermissionArea.General:     ...; break;
      case PermissionArea.Sistems:     ...; break;
      case PermissionArea.Support:     ...; break;
    }

    // output/use its description when needed:
    string permissionAreaText = permissionArea.Description();
    // ...

  } catch (Exception ex) {
    // error handling: short text is no permission area
    // ...
  }
}