我想在pattern-matching
上使用nullable int
,即int?
:
int t = 42;
object tobj = t;
if (tobj is int? i)
{
System.Console.WriteLine($"It is a nullable int of value {i}");
}
但是,这会导致以下语法错误:
'i)'标有红色波浪线。
使用旧操作符is
时表达式编译:
int t = 42;
object tobj = t;
if (tobj is int?)
{
System.Console.WriteLine($"It is a nullable int");
}
string t = "fourty two";
object tobj = t;
if (tobj is string s)
{
System.Console.WriteLine($@"It is a string of value ""{s}"".");
}
也按预期工作。
(我正在使用c#-7.2并使用.net-4.7.1和.net-4.6.1进行测试
我认为它与运营商优先级有关。因此,我尝试在几个地方使用括号,但这没有帮助。
为什么会出现这些语法错误,如何避免这些错误呢?
答案 0 :(得分:15)
各种形式的类型模式:x is T y
,case T y
等,always fails to match when x
is null
。这是因为null
doesn't have a type,所以问“这是这种null
吗?”是一个毫无意义的问题。
因此,t is int? i
或t is Nullable<int> i
作为一种模式毫无意义:t
是int
,在这种情况下,t is int i
无论如何都会匹配,或者它是null
,在这种情况下,任何类型模式都不会导致匹配。
这就是为什么t is int? i
或t is Nullable<int> i
不是,也可能永远不会被编译器支持的原因。
在使用t is int? i
时,您从编译器获得其他错误的原因是,例如, t is int? "it's an int" : "no int here"
是有效的语法,因此编译器会对您在此上下文中使用?
作为可空类型的尝试感到困惑。
至于如何避免它们,明显(尽管可能不是很有帮助)的答案是:不要使用可空类型作为类型模式中的类型。一个更有用的答案需要你解释为什么你试图这样做。
答案 1 :(得分:3)
对于任何想知道如何将模式匹配与nullable实际结合使用的人,可以使用通用的辅助函数来实现,例如:
public static bool TryConvert<T>(object input, out T output)
{
if (input is T result)
{
output = result;
return true;
}
output = default(T);
// Check if input is null and T is a nullable type.
return input == null && System.Nullable.GetUnderlyingType(typeof(T)) != null;
}
如果true
是与T
包含的类型相同的可空值或不可空值,或者input
为空且input
,则返回T
为空。基本上和普通的一样,但是也可以处理可空值。
旁注:有趣的是,从我的测试中,我发现System.Nullable.GetUnderlyingType(typeof(T))
在T可以为空时每次调用时分配40个字节的垃圾。不知道为什么,对我来说似乎是个错误,但这可能是要付出的高昂代价,而不是像通常那样仅进行空检查。
知道这一点,这是一个更好的功能:
public static bool TryConvert<T>(object input, out T? output) where T : struct
{
if (input is T result)
{
output = result;
return true;
}
output = default(T?);
return input == null;
}
答案 2 :(得分:2)
将您的代码更改为:
int t = 42;
object tobj = t;
if (tobj is Nullable<int> i)
{
Console.WriteLine($"It is a nullable int of value {i}");
}
这会产生更多帮助:
其他人(用户@Blue0500 at github)已将此行为标记为错误Roslyn issue #20156。对微软的Roslyn issue #20156,Julien Couvreur做出反应,他说他认为这是设计的 微软致力于Roslyn的Neal Gafter也说better diagnostics are wanted for use of nullable type is switch pattern。
因此,使用以下命令可以避免错误消息:
int t = 42;
object tobj = t;
if (tobj == null)
{
Console.WriteLine($"It is null");
}
else if (tobj is int i)
{
Console.WriteLine($"It is a int of value {i}");
}
除了issues when parsing tobj is int? i
之外,这仍然存在为什么tobj is int? i
或tobj is Nullable<int> i
不被允许的问题。