我刚刚将当前项目升级到新发布的 .NET Standard 2.1 和 C# 8.0,并决定将一些大型switch语句转换为新的、更紧凑的表达式语法。
由于返回的值在某些计算中进一步使用,我想知道switch当输入变量位于运算符旁边时新表达式的行为如何。
以下面的字符串连接为例:
string input = Console.ReadLine();
string output = "Letter: " + input switch
{
"1" => "a",
"2" => "b",
_ => "else"
};
Console.WriteLine(output);
Run Code Online (Sandbox Code Playgroud)
我猜想它switch与变量的绑定非常强烈input,因此首先被评估。事实上,Letter: a当我输入时,会打印出这样的内容1。
但我现在的问题是:这种行为是否适用于任何运营商?
从我的实验中,我无法确定上述假设不成立的情况,但这显然并不意味着我没有错过任何情况。该文档似乎也没有提到switch表达式上下文中的运算符优先级。还是我这里有更深层次的误解?
c# operator-precedence switch-statement c#-8.0 switch-expression
Visual Studio 2019 建议将我编写的 switch 语句转换为 switch表达式(两者都包含在下面用于上下文)。
对于这样的简单示例,将其编写为表达式是否有任何技术或性能优势?例如,这两个版本的编译方式是否不同?
陈述
switch(reason)
{
case Reasons.Case1: return "string1";
case Reasons.Case2: return "string2";
default: throw new ArgumentException("Invalid argument");
}
Run Code Online (Sandbox Code Playgroud)
表达
return reason switch {
Reasons.Case1 => "string1",
Reasons.Case2 => "string2",
_ => throw new ArgumentException("Invalid argument")
};
Run Code Online (Sandbox Code Playgroud) 其他一些高级语言(如Haskell和Perl 6)提供了语法糖,即使在语法需要对象的地方也可以抛出异常.当使用该值时,它就好像变成抛出的异常(在下面非常人为的例子中会立即出现):
enum BuildMode { Debug, MemoryProfiling, Release };
bool IsDebugMode(BuildMode mode)
{
return mode == BuildMode.Debug ? true
: mode == BuildMode.MemoryProfiling ? true
: mode == BuildMode.Release ? false
: ThrowException<bool>("Unhandled mode: " + mode);
}
Run Code Online (Sandbox Code Playgroud)
上面的帮助器允许从允许值但不是语句的地方抛出异常.我可以按如下方式编写这个函数,虽然它不像Haskell或Perl 6代码那么酷,因为没有懒惰的评估:
T ThrowException<T>(string message)
{
#line hidden
throw new Exception(message);
#line default
}
Run Code Online (Sandbox Code Playgroud)
有没有任何规范的方法来做到这一点,或者有什么好的理由不去做?
编辑:
throw new Exception()在发布之前,我实际上没有尝试在C#7中使用它作为值.这或多或少都是答案.我将把它留下来,以防将来人们搜索与Perl 6 Failure类或Haskell 相当的C#error.
我在看这段代码:
public enum MO
{
Learn, Practice, Quiz
}
public enum CC
{
H
}
public class SomeSettings
{
public MO Mode { get; set; }
public CC Cc { get; set; }
}
static void Main(string[] args)
{
var Settings = new SomeSettings() { Cc = CC.H, Mode = MO.Practice };
var (msg,isCC,upd) = Settings.Mode switch {
case MO.Learn => ("Use this mode when you are first learning the phrases and their meanings.",
Settings.Cc == CC.H,
false),
case MO.Practice …Run Code Online (Sandbox Code Playgroud) C# 8 引入了模式匹配,我已经找到了使用它的好地方,比如这个:
private static GameType UpdateGameType(GameType gameType)
{
switch (gameType)
{
case GameType.RoyalBattleLegacy:
case GameType.RoyalBattleNew:
return GameType.RoyalBattle;
case GameType.FfaLegacy:
case GameType.FfaNew:
return GameType.Ffa;
default:
return gameType;
}
}
Run Code Online (Sandbox Code Playgroud)
然后变成
private static GameType UpdateGameType(GameType gameType) => gameType switch
{
GameType.RoyalBattleLegacy => GameType.RoyalBattle,
GameType.RoyalBattleNew => GameType.RoyalBattle,
GameType.FfaLegacy => GameType.Ffa,
GameType.FfaNew => GameType.Ffa,
_ => gameType;
};
Run Code Online (Sandbox Code Playgroud)
但是,你可以看到我现在不得不提GameType.RoyalBattle和GameType.Ffa两次。有没有办法在模式匹配中一次处理多个案例?我正在考虑这样的事情,但它不是有效的语法:
private static GameType UpdateGameType(GameType gameType) => gameType switch
{
GameType.RoyalBattleLegacy, GameType.RoyalBattleNew => GameType.RoyalBattle,
GameType.FfaLegacy, GameType.FfaNew => GameType.Ffa,
_ => gameType; …Run Code Online (Sandbox Code Playgroud) 我试图了解 C# 8.0 switch 表达式的工作原理,但有几个问题。
null在默认情况下不能使用值?编译器抛出Cannot convert null to 'int' because it is a non-nullable value type错误。int函数的返回类型是“double?”?这是我正在玩的功能:
public static double? SwitchFunction(int x) =>
x switch
{
1 => 1,
_ => null
};
Run Code Online (Sandbox Code Playgroud)