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
// ...
}
}
首先我必须说我是 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
示例:
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
// ...
}
}