我已经编写了此方法,该方法根据表单提交的用户输入来“猜测”某种费用,以将真棒字体图标应用于该方法-在调用此方法之前已完成验证。如果没有条件匹配,则返回通用图标:
public static class IconService
{
public static string GuessExpenseIcon(string input)
{
string expenseName = input.ToLower();
string expenseIcon;
switch (expenseName)
{
case string a when a.Contains("phone"):
case string b when b.Contains("mobile"):
expenseIcon = "fas fa-mobile-alt";
break;
case string a when a.Contains("rent"):
case string b when b.Contains("mortgage"):
case string c when c.Contains("house"):
case string d when d.Contains("flat"):
case string e when e.Contains("apartment"):
expenseIcon = "fas fa-home";
break;
case string a when a.Contains("gas"):
case string b when b.Contains("util"):
expenseIcon = "fas fa-burn";
break;
case string a when a.Contains("electric"):
case string b when b.Contains("power"):
expenseIcon = "fas fa-bolt";
break;
case string a when a.Contains("petrol"):
case string b when b.Contains("diesel"):
case string c when c.Contains("fuel"):
expenseIcon = "fas fa-gas-pump";
break;
case string a when a.Contains("food"):
case string b when b.Contains("groceries"):
case string c when c.Contains("eat"):
case string d when d.Contains("take"):
expenseIcon = "fas fa-utensils";
break;
case string a when a.Contains("water"):
expenseIcon = "fas fa-shower";
break;
case string a when a.Contains("car"):
case string b when b.Contains("van"):
expenseIcon = "fas fa-car";
break;
case string a when a.Contains("internet"):
case string b when b.Contains("network"):
expenseIcon = "fas fa-wifi";
break;
case string a when a.Contains("spotify"):
expenseIcon = "fab fa-spotify";
break;
case string a when a.Contains("bus"):
case string b when b.Contains("coach"):
expenseIcon = "fas fa-bus";
break;
case string a when a.Contains("charity"):
case string b when b.Contains("donation"):
expenseIcon = "fas fa-hand-holding-heart";
break;
case string a when a.Contains("aws"):
expenseIcon = "fab fa-aws";
break;
default:
expenseIcon = "fas fa-money-bill-alt";
break;
}
return expenseIcon;
}
}
我的问题是:这么大的switch语句是实现这一目标的最佳方法吗?
我知道我可能只是过早地进行优化,因为我没有注意到负面的性能,但是由于某种原因,它对我来说似乎不合适。
我将定义一个词典并使用它:
public static class IconService
{
private static Dictionary<string, string> _expenseIcons = new Dictionary<string, string(StringComparer.OrdinalIgnoreCase) {
{ "phone", "fa-mobile-alt" },
{ "mobile", "fa-mobile-alt" },
{ "rent", "fa-mobile-alt" },
{ "mortgage", "fa-mobile-alt" },
{ "house", "fa-mobile-alt" },
{ "flat", "fa-mobile-alt" },
{ "apartment", "fa-mobile-alt" }
/* etc */
};
public static string GuessExpenseIcon(string input)
{
if (_expenseIcons.TryGetValue(input, out string expenseIcon)) // if the icon is found in the dictionary
{
return $"fas {expenseIcon}";
}
// default
return "fas fa-money-bill-alt";
}
}
我已经为字典键使用了不区分大小写的字符串比较器,因此您无需执行.ToLower()
位。我还从我们在词典中存储的内容中删除了图标的常见“ fas”部分,因为每个图标都有它。
我认为这不一定比您的switch
语句更好,但是这是一种更为优雅的解决方案,它还为更改_expenseIcons
的配置方式提供了可能性。例如,您可以从配置文件等中加载它。
就效率而言,我们将在应用程序/ appdomain的整个生命周期中初始化一次字典。字典本身的efficiency of lookups接近O(1):
通过使用其键检索值非常快,接近O(1),因为
Dictionary<TKey,TValue>
类被实现为哈希表。
怎么样?
class MatchPattern
{
public string [] Patterns {get;set;}
// This is to asume that you have more logic
// If all the logic of GetIcon is to return a simple string, you can
// replace with
// public string IconName {get;set;}
// instead.
public Func<string, string> GetIcon {get;set;}
}
public class IconService
{
private MatchPatterns[] _patterns;
public IconService()
{
_patterns=new []
{
new MatchPattern
{
Patterns=new[]{"phone", "mobile"},
GetIcon=(x)=>"fas fa-mobile-alt"
},
new MatchPattern
{
Patterns=new[]{"rent", "mortgage", "house", "flat", "apartment"},
GetIcon=(x)=>"fas fa-home"
}
,
// Here is more
}
}
public static string GuessExpenseIcon(string input)
{
foreach(var pattern in _patterns)
{
if(pattern.Any(item=>input.contains(item))
{
return pattern.GetIcon.Invoke(input);
}
}
}
}
使用Func可以解决以下情况:在不同情况下,您仍然具有一些稍微不同的逻辑。如果不是这种情况,则可以使用简单的IconName代替GetIcon Func。
class MatchPattern
{
public string [] Patterns {get;set;}
public string IconName {get;set;}
}
您可以处理每种情况的列表
foreach (var str in new string[] { "phone","mobile" }) {
if (expenseName.Contains(str)){
expenseIcon = "fas fa-mobile-alt";
}
}
也许值得研究Lambda表达式,这些表达式在Java中的语法较短,但是我不确定C#对它的支持程度如何