如何将C#中的可空整数转换为整数

586

如何将可空的 int 转换为 int?假设我有以下两种类型的 int:

int? v1;  
int v2; 

我想把v1的值赋给v2v2 = v1;会导致错误。如何将v1转换为v2


4
v1null时,期望的行为是什么? - Solomon Ucko
20个回答

771
到目前为止,其他答案都是正确的;我只想再加一点更加简洁的内容:
v2 = v1 ?? default(int);

任何 Nullable<T> 都可以隐式转换为其 T,前提是整个表达式的计算结果永远不会导致对 ValueType 的空赋值。因此,空合并运算符 ?? 只是三元运算符的语法糖:

v2 = v1 == null ? default(int) : v1.Value;

这实际上是if/else的简写语法:

if(v1==null)
   v2 = default(int);
else
   v2 = v1.Value;

此外,在.NET 4.0及以上版本中,Nullable<T>有一个“GetValueOrDefault()”方法,它是一个空值安全的getter,基本上执行了上面所示的null-coalescing操作,因此这也可以工作:
v2 = v1.GetValueOrDefault();

5
default(int) 真的必要吗?使用简单的 0 有什么问题吗? - Cole Tobin
6
这个例子可能可以用,但在一般情况下建议使用“default”(默认值)。零并不总是一个有效的值,更不要说作为默认值了。因此,如果您用通用型“T”来替换“int”,您会发现我的代码可以工作,而零则不行。在将来的某个框架版本中,“default”也可能会成为可重载的;如果发生这种情况,使用“default”的代码将很容易地利用它,而显式的null或零赋值则必须被改变。 - KeithS
17
这应该被置于顶部:.NET 4.0中,Nullable<T>拥有一个“GetValueOrDefault()”方法。 - RandomHandle
由于.NET 4已经发布很长时间了,因此编辑此帖子以使GetValueOrDefault显示为主要答案会很好。 - Andy
3
通过VS2019的建议,v2 = v1 ?? default; - wolf354
显示剩余3条评论

211

像这样,

if(v1.HasValue)
   v2=v1.Value

126
你可以使用Value属性进行赋值。
v2 = v1.Value;

8
如果你不确定v1是否为空,你可以使用null-coalescing运算符来设置一个备用值。例如:v2 = v1 ?? 0; - Arjen
16
确保首先检查v1.HasValue - Yuck
4
MSDN所述,如果变量v1null,则会抛出异常。我认为这不是正确的答案。 - ventiseis
9
我认为这是一种理想的行为 - 我很惊讶其他答案居然默认将空值静默地转换成0。如果你将可为空类型赋给不可为空类型,你应该确保该值实际上不是空。原帖没有说“我想将v1赋给v2,如果v1为空则赋值为0”,但似乎每个人都是这样假设的。 - Michael Mrozek
我不记得哪个版本的C#引入了!运算符(空值容忍),但由于业务逻辑,我知道int?不是空值。我使用v2 = v1!.Value来获取我的值。正如@MichaelMrozek指出的,我确实希望抛出异常,因为我的业务逻辑出了问题。顺便说一下,我需要一个非空的int,以便将其传递给另一个函数。 - undefined

97

你所需要的就是...

v2= v1.GetValueOrDefault();

2
请注意,如果它为null,则返回0。 - CageE

58

如果v1为空,你无法这样做,但是你可以使用运算符进行检查。

v2 = v1 ?? 0;

1
这个对我来说是最有用的。 - Sarasjd

54

如果你知道v1有一个值,你可以使用Value属性:

v2 = v1.Value;

使用GetValueOrDefault方法将赋值为该值(如果存在),否则为类型的默认值或您指定的默认值:
v2 = v1.GetValueOrDefault(); // assigns zero if v1 has no value

v2 = v1.GetValueOrDefault(-1); // assigns -1 if v1 has no value

你可以使用HasValue属性来检查v1是否有值:
if (v1.HasValue) {
  v2 = v1.Value;
}

此外,GetValueOrDefault(T)方法也有语言支持:

v2 = v1 ?? -1;

在使用值之前,应首先检查是否存在该值。请改用 ?? 运算符。 - Peter

31

GetValueOrDefault()

GetValueOrDefault() 方法获取对象的值。如果该对象为 null,则返回 int 类型的默认值,即0。

例如:

v2= v1.GetValueOrDefault();


28

如果给定类型的默认值是可接受的结果:

if (v1.HasValue)
    v2 = v1.GetValueOrDefault();

如果您希望在结果为未定义时设置不同的默认值:

v2 = v1.GetValueOrDefault(255);    // or any valid value for int in place of 255

如果你只想要返回值(无论方法是否失败):
v2 = v1.GetValueOrDefault();


.NET 4.7.2: GetValueOrDefault()方法在不进行任何检查的情况下返回字段值。


19

根据您的使用情况,您可以使用C# 7的模式匹配功能:

int? v1 = 100;
if (v1 is int v2)
{
    Console.WriteLine($"I'm not nullable anymore: {v2}");
}

编辑:

由于一些人没有留下解释就进行了负评,我想补充一些细节来解释将此作为可行解决方案的理由。

  • C# 7的模式匹配现在允许我们检查一个值的类型并隐式地强制转换它。在上面的代码片段中,当存储在v1中的值与v2的类型兼容时(在本例中是int),if条件才会通过。因此,当v1的值为null时,if条件将失败,因为null不能赋给int。更准确地说,null不是int

  • 需要强调的是,这种解决方案可能并不总是最佳选择。正如我所建议的那样,我相信这将取决于开发者的具体使用情境。如果您已经有一个int?并且希望在分配值不为null时有条件地对其进行操作(这是将可空int转换为常规int而不会丢失信息的唯一安全时间),那么模式匹配可能是最简洁的方法之一。


引入新的变量名的必要性是不幸的,但如果没有默认值,这是最好(最安全)的解决方案,因为没有意外地重构您的HasValue检查的风险。 - minexew
我只是看不到这种方法相对于v1.HasValue的优势,因为要先检查再访问底层值。我不会踩反对票,但我认为这个问题已经得到解决,新技术对问题的澄清并没有太多帮助。我还进行了基准测试,结果显示比原来慢了8-9%。 - Brandon Barkley
谢谢你对它进行基准测试,这很好知道!无论如何,最多只有微小的差异(除非您在某些时间关键的领域中执行此操作)。我认为这更加“简洁”或可能是“惯用语”,因为它依赖于内置到语言中的语法糖而不是API。这有点主观,但也许它更“可维护”。尽管真的,我比其他答案建议的依赖默认值更喜欢这种方法。 - Nicholas Miller
它速度较慢的事实很不幸,因为这似乎具有消除重复检查可能性的优势,但如果它使用硬转换作为检查本身,我想知道速度缓慢的原因是否是基础异常使用... - bug

19

我认为最好的解决方案是使用 GetValueOrDefault() 方法。

v2 = v1.GetValueOrDefault();

这个对我来说最有用。 - Liakat Hossain
1
请注意,如果它为null,则返回0。 - Sarasjd

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接