我有一个方法使用一长串if / elseif语句(大约10-15),我明白当你通过大约5 if / else if语句时,最好使用一个开关。话虽这么说,我不确定我可以在我的情况下使用switch语句,因为我的if / else if语句依赖于测试字符串,而不是相等,而是使用Contains()方法。所以,现在我有相当于
的东西string s = "ABCD";
if(s.Contains("A")
{
//do stuff
}
else if(s.Contains("E")
{
//do different stuff
}
etc ...
我尝试过不同的方法来实现switch语句,例如
switch()
{
case(s.Contains("A"))
{
//do stuff
}
}
但我尝试的每种方式都会导致语法错误。
有没有办法在使用Contains()方法测试字符串时使用switch语句?
答案 0 :(得分:3)
不,switch
语句需要案例标签的常量值。所以一般来说,最好坚持使用if
语句。但这与您在场景中使用switch
语句的距离非常接近。
string myString = "ABC";
List<string> subStrings = new List<string>{"A", "B", "C"};
switch (subStrings.FirstOrDefault(myString.Contains))
{
case "A":
Console.WriteLine("Has A");
break;
case "B":
Console.WriteLine("Has B");
break;
case "C":
Console.WriteLine("Has C");
break;
default:
Console.WriteLine("No ABC");
break;
}
我怀疑它会比if
语句更快,因为FirstOrDefault
基本上做同样的事情,它打破了DRY主体,因为它需要更新列表和{{1声明。
答案 1 :(得分:1)
首先想到的是
string s = "ABCD";
foreach (char oneChar in s.ToCharArray())
{
switch (oneChar)
{
case 'A':
Console.WriteLine("Do A stuff");
break;
case 'B':
Console.WriteLine("Do B stuff");
break;
case 'C':
Console.WriteLine("Do C stuff");
break;
case 'D':
Console.WriteLine("Do D stuff");
break;
default:
break;
}
}
取决于你在做什么,这可能是也可能不是一种有效的方式。如果字符串中的大多数字符实际上导致分支到这些情况之一,那么这将更有效,因为您不必进行一堆字符串包含搜索。如果字符串中有很多字符没有匹配的分支(它们什么也不做),那么这可能不是一种有效的方法。
答案 2 :(得分:1)
string input = "ABDE";
var mapping = new Dictionary<Func<string, bool>, Action<string>>()
{
{ (string i) => i.Contains("A"), (string i) => Console.WriteLine("Found input with 'A'") },
{ (string i) => i.Contains("B"), (string i) => Console.WriteLine("Found input with 'B'") },
{ (string i) => i.Contains("C"), (string i) => Console.WriteLine("Found input with 'C'") },
{ (string i) => i.Contains("D"), (string i) => Console.WriteLine("Found input with 'D'") }
};
foreach (var criteria in mapping)
{
if (criteria.Key(input)) {
criteria.Value(input);
break;
}
}
通过这种方式将测试/操作条件组合在一起,您可以使用foreach干净地运行所有规则而无需太多工作,并且添加/删除规则更容易。
答案 3 :(得分:1)
使用C#7.0中的pattern matching feature,现在可以在switch语句中使用Contains。提供比多个if else块更清晰的代码。以下代码示例显示了如何执行此操作
var patterns = new[] { "dog", "cat", "cats and dogs", "parrot", "parrot and cat" };
foreach (var item in patterns)
{
switch (item)
{
case var s when s.Contains("cat"):
Console.WriteLine($"{item} contains cat");
break;
case var s when s.Contains("dog"):
Console.WriteLine($"{item} contains dog");
break;
case var s when s.Contains("parrot"):
Console.WriteLine($"{item} contains parrot");
break;
}
}
请注意,它不适用于早于C#7.0的版本。
答案 4 :(得分:0)
如果您有很多这些行,有时使用字典将目标值映射到操作可以更清晰,更灵活,例如:
using System;
using System.Collections.Generic;
using System.Linq;
namespace ConsoleApplication1
{
public class Program
{
static void Main()
{
var dict = new Dictionary<string, Action<string>>
{
["A"] = Console.WriteLine,
["B"] = doSomething1,
["C"] = doSomething2,
["D"] = str => Console.WriteLine("Inline: " + str)
};
string s = "ABCD";
string first = dict.Keys.FirstOrDefault(t => s.Contains(t));
if (first != null)
dict[first](first);
else
; // Default behaviour.
}
private static void doSomething1(string x)
{
Console.WriteLine("doSomething1 with " + x);
}
private static void doSomething2(string x)
{
Console.WriteLine("doSomething2 with " + x);
}
}
}
“更灵活”我的意思是你可以传递字典,如果你想在一个地方映射动作并在其他地方使用它。
(这使用C#6语法初始化字典。)
说了这么多,在我看来是一个不必要的复杂功能,除非你想传递字典。如果不这样做,那么只使用if / else级联可能是最好的方法。
(注意:这个答案与Mike Corcoran的相似 - 我在写作的同时也是他的,似乎。我会把它留在这里,因为它需要稍微不同的方法。)