如何将C#可为空的int转换为int


482

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

int? v1;  
int v2; 

我想将v1的值分配给v2v2 = v1;会导致错误。我如何转换v1v2


什么时候v1是期望的行为null
所罗门·乌科

Answers:


636

到目前为止,其他答案都是正确的。我只想再添加一个稍微干净一点的:

v2 = v1 ?? default(int);

Any Nullable<T>可以隐式转换为它的T,条件是要求值的整个表达式永远不会导致对ValueType的空赋值。因此,null-coalescing运算符??只是三元运算符的语法糖:

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

...这反过来是if / else的语法糖:

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

而且,从.NET 4.0开始,Nullable<T>具有“ GetValueOrDefault()”方法,该方法是一个空值安全的获取器,基本上执行上面显示的空值合并,因此也可以使用:

v2 = v1.GetValueOrDefault();

4
是否default(int)真的需要?简单有什么问题0
科尔·约翰逊

4
该示例适用于此示例,但在一般情况下,建议default在适当的地方使用。零并不总是有效的值,更不用说默认值了,因此,如果int用泛型替换,T我的代码会工作而零则无效。在某些将来的框架版本中,default也可能变得可重载;如果发生这种情况,那么使用default的代码将很容易利用,而显式的null或0分配则必须更改。
KeithS 2015年

5
这应该上升到顶部:.NET 4.0,Nullable <T>具有一个“ GetValueOrDefault()”
RandomHandle

感谢您回来使用GetValueOrDefault对其进行编辑!
CindyH

使用默认值时,您可能要小心使用DateTime。这可能会插入默认日期而不是空日期。
Ranch Camal


92

您可以使用Value属性进行分配。

v2 = v1.Value;

8
另外-如果不确定v1是否包含null,则可以使用null-coalescing运算符设置后备值。例如v2 = v1 ?? 0;
阿延

12
并且一定v1.HasValue要先检查。
uck

3
MSDN说,如果v1is ,这将引发异常null。我认为这不是正确的答案。
ventiseis

6
@ventiseis我认为这是理想的行为-令我惊讶的是,许多其他答案都可以通过将null静默转换为0来解决。该值实际上不是null。OP并没有说“我想将v1分配给v2,如果v1为空,则将其分配为0”,但这就是每个人似乎都假设的
Michael Mrozek

82

所有你需要的是..

v2= v1.GetValueOrDefault();

49

如果您知道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;

在未首先检查是否存在值的情况下,不应使用该值。使用 ??运算符。
彼得


28

GetValueOrDefault()

检索对象的值。如果为null,则返回int的默认值,即0。

例:

v2= v1.GetValueOrDefault();


21

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

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()不进行任何检查就返回该字段值。




10

有可能 v2 = Convert.ToInt32(v1);


从技术上讲这将起作用,但是其他技术(例如HasValue / Value或GetValueOrDefault)的运行效率更高。
布兰登·巴克利


9

v1和之间v2无法进行简单转换,因为v1的值域大于v2。一切都v1可以容纳,还有null状态。要进行转换,您需要明确说明int将使用哪些值来映射null状态。最简单的方法是??操作员

v2 = v1 ?? 0;  // maps null of v1 to 0

这也可以用长格式完成

int v2;
if (v1.HasValue) {
  v2 = v1.Value;
} else {
  v2 = 0;
}

9

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

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

编辑:

由于有些人在不加解释的情况下不满意,我想添加一些细节来解释将其作为可行解决方案的理由。

  • C#7的模式匹配现在允许我们检查值的类型并将其隐式转换。在上面的代码段中,当存储在值如果条件将只传递v1的类型兼容的该类型v2,在这种情况下是int。因此,当for的值为v1is时null,if条件将失败,因为无法将null分配给int。更恰当的null是,不是int

  • 我想强调一点,这种解决方案可能并不总是最佳选择。正如我建议的那样,我相信这将取决于开发人员的确切使用情况。如果您已经有一个int?并且想要有条件地对它的值进行if-and-only-(如果分配的值不为null)(这是唯一可以安全地将可为null的int转换为常规int而不会丢失信息的情况),那么模式匹配也许是最简洁的方法之一。


不幸的是,必须引入新的变量名,但是如果没有默认值,这是最好的(最安全的)解决方案,因为不存在意外重构HasValue支票的风险。
minexew

我只是没有看到此方法相对于v1.HasValue作为检查对象,然后再访问v1.Value来访问基础值没有任何优势。我不会拒绝投票,但是我认为这个问题已经解决,并且新技术并不能使问题更加清晰。我还将基准测试的速度降低了8-9%。
布兰登·巴克利

感谢您对它进行基准测试,这很高兴知道!无论您以哪种方式看待,差异最多都是微不足道的(除非您认为在某些时间紧迫的领域中这样做)。我认为这更“简洁”或“惯用”,因为它依赖于语言中的语法糖而不是API。这有点主观,但也许“更易于维护”。尽管确实如此,但我更喜欢这种方法,而不是像许多其他答案所建议的那样依赖默认值。
尼古拉斯·米勒

3

如果不为null,它将分配v1to的v2值,否则它将默认值为零。

v2=v1??0

或下面是写它的另一种方法。

v2 = v1.HasValue?v1:0


-1
 int v2= Int32.Parse(v1.ToString());

5
尽管此代码可以回答问题,但提供有关此代码为何和/或如何回答问题的其他上下文,可以提高其长期价值。
夏威

1
最好使用“最佳实践”方法来解开可选项,而不要使用不熟练的技巧。请参阅docs.microsoft.com/en-us/dotnet/csharp/language-reference/…以获取参考
lorg

当用一个已有的十五个答案回答一个已有八年历史的问题时,重要的是要解释您的答案所要解决的问题的新方面,并注意时间的流逝是否改变了答案。通过仅添加一些解释,几乎只能对仅代码的答案进行改进。
Jason Aller
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.