如何判断System.ValueTuple是否为默认值?
如何判断System.ValueTuple是否为默认值?
这个问题我之前踩过坑,确实ValueTuple的默认值判断逻辑和普通引用/值类型有点不一样,咱们来拆解下问题和可行的解决方案:
首先先说说你尝试的几种写法为啥不生效:
result is default:C#的is表达式里直接写default是不合法的,编译器没法推断出要匹配的具体类型,所以这个写法本身就通不过编译或者不会按预期工作。result == default:如果你的项目用的是C# 7.3之前的版本,ValueTuple并没有默认实现==运算符,所以这个写法会报错;如果是7.3+版本,其实这个是可以正常工作的,可能你之前的环境版本不对?result is default(string, string):这个写法在C# 8.0+的模式匹配里是支持的,但如果版本较低,编译器可能不识别这种语法。
接下来分版本给出靠谱的解决方案:
方案1:使用C# 7.3及以上版本(推荐)
从C# 7.3开始,ValueTuple类型正式支持了==和!=运算符,编译器会自动逐个比较元组的每个元素是否都为对应类型的默认值。所以你可以直接用两种写法:
var result = MyMethod(); // 写法1:利用类型推断,直接和default比较 if (result == default) { // 是默认值 } // 写法2:明确指定元组类型 if (result == default((string, string))) { // 是默认值 }
因为你的MyMethod返回的是命名元组(string foo, string bar),而命名元组本质是ValueTuple的语法糖,所以上面的判断完全适用。
方案2:C# 7.2及以下版本(兼容旧环境)
如果你的项目没法升级到7.3+,那只能手动判断每个元素是否为默认值:
写法1:直接判断每个成员
var result = MyMethod(); if (result.foo == default(string) && result.bar == default(string)) { // 是默认值 }
对于值类型的元组元素(比如int),直接和default(T)或者对应的默认值(比如0)比较就行;对于引用类型,就是和null比较。
写法2:封装扩展方法复用逻辑
如果需要多次判断,可以写一个通用的扩展方法,避免重复代码:
using System.Collections.Generic; public static class TupleExtensions { public static bool IsDefault<T1, T2>(this (T1, T2) tuple) { return EqualityComparer<T1>.Default.Equals(tuple.Item1, default) && EqualityComparer<T2>.Default.Equals(tuple.Item2, default); } // 如果需要支持更多元素的元组,可以继续重载: public static bool IsDefault<T1, T2, T3>(this (T1, T2, T3) tuple) { return EqualityComparer<T1>.Default.Equals(tuple.Item1, default) && EqualityComparer<T2>.Default.Equals(tuple.Item2, default) && EqualityComparer<T3>.Default.Equals(tuple.Item3, default); } }
然后调用的时候就很简洁:
var result = MyMethod(); if (result.IsDefault()) { // 是默认值 }
另外补充个小技巧:如果是在C# 8.0及以上,还可以用模式匹配的写法:
if (result is (default, default)) { // 是默认值 }
这个写法会逐个匹配元组的元素是否为对应类型的默认值,看起来更直观。
内容的提问来源于stack exchange,提问作者nawfal
相关产品推荐
相关产品推荐

