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

Posted

技术标签:

【中文标题】如何将 C# 可为空的 int 转换为 int【英文标题】:How to convert C# nullable int to int 【发布时间】:2011-08-25 02:48:45 【问题描述】:

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

int? v1;  
int v2; 

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

【问题讨论】:

v1null 时,期望的行为是什么? 【参考方案1】:

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

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()”方法,它是一个 null 安全的 getter,基本上执行上面显示的 null 合并,所以这也有效:

v2 = v1.GetValueOrDefault();

【讨论】:

真的需要default(int) 吗?一个简单的0 有什么问题? 它适用于本示例,但在一般情况下,建议在适当的情况下使用default。零作为一个值并不总是有效的,更不用说默认值了,所以如果你用通用的T 替换int,你会发现我的代码有效,而零无效。在某些未来的框架版本中,default 也可能变得可重载;如果发生这种情况,使用默认值的代码将很容易利用,而显式的 null 或零分配将不得不更改。 这应该上升到顶部:.NET 4.0,Nullable 有一个“GetValueOrDefault()” 感谢您回来使用 GetValueOrDefault 编辑它! 由 VS2019 建议 v2 = v1 ??默认;【参考方案2】:

这样,

if(v1.HasValue)
   v2=v1.Value

【讨论】:

【参考方案3】:

您可以使用 Value 属性进行赋值。

v2 = v1.Value;

【讨论】:

另外——如果你不确定 v1 是否包含 null——你可以使用 null-coalescing 操作符来设置一个后备值。例如。 v2 = v1 ?? 0; 并且一定要先检查v1.HasValue MSDN 说,如果v1null,这将引发异常。在我看来,这不是一个正确的答案。 @ventiseis 我认为这是可取的行为——我很惊讶许多其他答案都可以默默地将 null 转换为 0。如果您将可空类型分配给非可空类型,您应该确保该值实际上不是空的。 OP 没有说“我想将 v1 分配给 v2,或者如果 v1 为空,则为 0”,但这似乎是每个人的假设【参考方案4】:

你只需要..

v2= v1.GetValueOrDefault();

【讨论】:

请注意,如果它为空,则返回 0【参考方案5】:

如果 v1 为 null,则无法执行此操作,但可以通过操作员检查。

v2 = v1 ?? 0;

【讨论】:

这个对我最有用【参考方案6】:

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

【讨论】:

您不应该在没有先检查是否有值的情况下使用该值。使用 ??运算符。【参考方案7】:

GetValueOrDefault()

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

例子:

v2= v1.GetValueOrDefault();

【讨论】:

【参考方案8】:

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

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

【讨论】:

【参考方案9】:

就我而言,最好的解决方案是使用GetValueOrDefault() 方法。

v2 = v1.GetValueOrDefault();

【讨论】:

这个对我最有用 请注意,如果它为空,则返回 0【参考方案10】:

根据您的使用上下文,您可以使用 C# 7 的模式匹配功能:

int? v1 = 100;
if (v1 is int v2)

    Console.WriteLine($"I'm not nullable anymore: v2");

编辑:

由于有些人在不解释的情况下投了反对票,我想补充一些细节来解释将其作为可行解决方案的理由。

C# 7's pattern matching 现在允许我们检查值的类型并隐式转换它。在上面的 sn-p 中,只有当存储在 v1 中的值与 v2 的类型兼容时,if 条件才会通过,在这种情况下是 int。因此,当v1 的值为null 时,if 条件将失败,因为 null 不能分配给int。更准确地说,null 不是 int

我想强调的是,这种解决方案可能并不总是最佳选择。正如我所建议的,我相信这将取决于开发人员的确切使用上下文。如果您已经有一个int? 并希望对其值进行有条件地操作if-and-only-if,则分配的值不为空(这是唯一可以安全地转换可为空的 int到一个常规的 int 而不会丢失信息),那么模式匹配可能是最简洁的方法之一。

【讨论】:

不幸的是,引入新变量名的必要性,但如果没有默认值,这是最好(最安全)的解决方案,因为不存在意外重构 HasValue 检查的风险。 我只是没有看到这种方法比 v1.HasValue 作为检查然后 v1.Value 访问基础值有任何优势。我不会反对它,但我认为这个问题已经解决了,而且新技术并没有使问题更加清晰。我还将它的基准测试为慢了 8-9%。 感谢您对其进行基准测试,很高兴知道!无论您怎么看,差异充其量是微不足道的(除非您在我认为的某个时间关键区域这样做)。我认为这更“简洁”或可能“惯用”,因为它依赖于语言中的语法糖而不是 API。这有点主观,但也许它“更易于维护”。尽管确实如此,但我更喜欢这种方法,而不是像许多其他答案所暗示的那样依赖默认值。【参考方案11】:

Int nullable 到 int 的转换可以这样完成:

v2=(int)v1;

【讨论】:

如果 v1 为 null,这将导致 InvalidOperationException。【参考方案12】:

在 C# 7.1 及更高版本中,可以使用 default literal 而不是 default operator 来推断类型,因此可以编写如下:

v2 = v1 ?? default;

【讨论】:

【参考方案13】:

v2 = Convert.ToInt32(v1); 可以实现

【讨论】:

这在技术上是可行的,但其他技术如 HasValue / Value 或 GetValueOrDefault 运行效率更高。【参考方案14】:

你可以的

v2 = v1.HasValue ? v1.Value : v2;

【讨论】:

【参考方案15】:

v1v2 之间的简单转换是不可能的,因为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;

【讨论】:

【参考方案16】:

如果v1不为空,则将v1赋值给v2,否则默认为零。

v2=v1??0

或者下面是另一种写法。

v2 = v1.HasValue?v1:0

【讨论】:

【参考方案17】:

可以使用以下任何一种转换方法来完成:

v2 = Convert.ToInt32(v1);

v2 = (int)v1;

v2 = v1.GetValueOrDefault();

v2 = v1.HasValue ? v1:0;

【讨论】:

【参考方案18】:
 int v2= Int32.Parse(v1.ToString());

【讨论】:

虽然此代码可能会回答问题,但提供有关此代码为何和/或如何回答问题的额外上下文可提高其长期价值。 最好使用“最佳实践”的方式来解开可选项,而不是使用卑鄙的技巧。请参阅docs.microsoft.com/en-us/dotnet/csharp/language-reference/… 以供参考 在回答一个已有 15 个已有答案的 8 岁问题时,重要的是要说明您的答案所针对的问题的新方面,并注意时间的流逝是否改变了答案。添加一些解释几乎总是可以改进仅代码的答案。 我想这比其他答案要慢得多,绕道而行。仍然失败为空 我只是做了一个简单的测试:通过字符串往返它比其他一些选项慢大约 60 倍。高达 100 纳秒!【参考方案19】:

我正在研究 C# 9 和 .NET 5,例如

foo 是可空的 int,我需要获取 foo 的 int 值

var foo = (context as AccountTransfer).TransferSide;
int value2 = 0;
if (foo != null)

    value2 = foo.Value;

在https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/nullable-value-types#examination-of-an-instance-of-a-nullable-value-type查看更多信息

【讨论】:

【参考方案20】:

普通的TypeConversion会抛出异常

例如:

int y = 5;    
int? x = null;    
y = x.value; //It will throw "Nullable object must have a value"   
Console.WriteLine(y);

使用Convert.ToInt32()方法

int y = 5;    
int? x = null;    
y = x.Convert.ToInt32(x);    
Console.WriteLine(y);

这将返回 0 作为输出,因为 y 是一个整数。

【讨论】:

欢迎来到 ***。没有x.Convert这样的东西,请修复提供的示例。

以上是关于如何将 C# 可为空的 int 转换为 int的主要内容,如果未能解决你的问题,请参考以下文章

如何将 int.TryParse 与可为空的 int 一起使用? [复制]

将 int.TryParse 与可为空的 int 一起使用 [重复]

使用 XmlSerializer 将空 xml 属性值反序列化为可为空的 int 属性

将可为空的 int 映射到可为空的 int + automapper

在 clickhouse 中,使用强制转换函数时如何为可为空的列返回 null

序列化一个可为空的 int