【问题标题】:Conditional operator assignment with Nullable<value> types?Nullable<value> 类型的条件运算符赋值?
【发布时间】:2018-07-04 23:41:23
【问题描述】:
EmployeeNumber =
string.IsNullOrEmpty(employeeNumberTextBox.Text)
    ? null
    : Convert.ToInt32(employeeNumberTextBox.Text),

我经常发现自己想做这样的事情(EmployeeNumberNullable&lt;int&gt;,因为它是 LINQ-to-SQL dbml 对象的属性,其中列允许 NULL 值)。不幸的是,编译器认为

'null' 和 'int' 之间没有隐式转换

即使这两种类型在对可空 int 的赋值操作中都是有效的。

据我所知,使用空合并运算符不是一个选项,因为如果.Text 字符串不为空,则需要在该字符串上进行内联转换。

据我所知,唯一的方法是使用 if 语句和/或分两步分配它。在这种特殊情况下,我发现这非常令人沮丧,因为我想使用对象初始化器语法,而这个赋值将在初始化块中......

有人知道更优雅的解决方案吗?

【问题讨论】:

标签: c# conditional-operator nullable


【解决方案1】:

出现问题是因为条件运算符不查看值是如何使用(在本例中是分配)来确定表达式的类型——只查看真/假值。在这种情况下,您有一个null 和一个Int32,并且无法确定类型(有真正的原因不能只假设Nullable&lt;Int32&gt;)。

如果真的要这样使用,必须自己将其中一个值强制转换为Nullable&lt;Int32&gt;,这样C#才能解析类型:

EmployeeNumber =
    string.IsNullOrEmpty(employeeNumberTextBox.Text)
    ? (int?)null
    : Convert.ToInt32(employeeNumberTextBox.Text),

EmployeeNumber =
    string.IsNullOrEmpty(employeeNumberTextBox.Text)
    ? null
    : (int?)Convert.ToInt32(employeeNumberTextBox.Text),

【讨论】:

  • 你也可以写new int?()
  • 你说它不能假设为 Nullable 有真正的原因。什么原因?
  • @SLaks 或 default(int?).
  • 真正的原因?我也看不出真正的原因。
【解决方案2】:

截至C# 9.0,这将最终成为可能:

目标类型 ??和?:

有时是有条件的??和 ?: 表达式在分支之间没有明显的共享类型。这种情况今天失败了,但如果有两个分支都转换为的目标类型,C# 9.0 将允许它们:

Person person = student ?? customer; // Shared base type
int? result = b ? 0 : null; // nullable value type

这意味着问题中的代码块也将无错误地编译。

EmployeeNumber =
string.IsNullOrEmpty(employeeNumberTextBox.Text)
    ? null
    : Convert.ToInt32(employeeNumberTextBox.Text),

【讨论】:

    【解决方案3】:
    //Some operation to populate Posid.I am not interested in zero or null
    int? Posid = SvcClient.GetHolidayCount(xDateFrom.Value.Date,xDateTo.Value.Date).Response;
    var x1 = (Posid.HasValue && Posid.Value > 0) ? (int?)Posid.Value : null;
    

    编辑: 上面的简要说明,我试图在变量X1 中获取Posid 的值(如果它的非空int 并且值大于0)。我必须在Posid.Value 上使用(int?) 才能使条件运算符不引发任何编译错误。 仅供参考 GetHolidayCount 是一个 WCF 方法,可以给出 null 或任何数字。 希望有帮助

    【讨论】:

    • 通常建议您包含对代码功能的描述,而不仅仅是发布代码。这有助于提出问题的人(以及在遇到相同问题时发现此问题的人)了解您的解决方案在做什么。
    【解决方案4】:

    虽然 Alex 为您的问题提供了正确且最接近的答案,但我更喜欢使用 TryParse

    int value;
    int? EmployeeNumber = int.TryParse(employeeNumberTextBox.Text, out value)
        ? (int?)value
        : null;
    

    它更安全,可以处理无效输入的情况以及您的空字符串情况。否则,如果用户输入1b 之类的内容,他们将看到一个错误页面,其中包含Convert.ToInt32(string) 中导致的未处理异常。

    【讨论】:

    • 我更喜欢使用 ASP.NET CompareValidator 来验证用户的输入,它可以设置为 DataTypeCheck 的运算符和 int 的类型。这样可以确保输入永远不会是整数以外的任何内容,如果可以的话,它会在客户端进行。
    【解决方案5】:

    我认为实用方法可以帮助使这个更清洁。

    public static class Convert
    {
        public static T? To<T>(string value, Converter<string, T> converter) where T: struct
        {
            return string.IsNullOrEmpty(value) ? null : (T?)converter(value);
        }
    }
    

    然后

    EmployeeNumber = Convert.To<int>(employeeNumberTextBox.Text, Int32.Parse);
    

    【讨论】:

    • 这是一个非常好的主意,也是泛型和扩展方法非常棒的一个例子:)
    【解决方案6】:

    你可以转换转换的输出:

    EmployeeNumber = string.IsNullOrEmpty(employeeNumberTextBox.Text)
       ? null
       : (int?)Convert.ToInt32(employeeNumberTextBox.Text)
    

    【讨论】:

      猜你喜欢
      • 2018-06-09
      • 2011-09-18
      • 2015-06-06
      • 2011-03-11
      • 1970-01-01
      • 1970-01-01
      • 2015-07-16
      相关资源
      最近更新 更多