【问题标题】:Converting null literal or possible null warning on DataRow in foreach在 foreach 中的 DataRow 上转换 null 文字或可能的 null 警告
【发布时间】:2020-08-19 22:54:06
【问题描述】:

更新了我的 .NET Core 3.1 控制台应用程序以使用 Nullables 功能并具有以下 foreach 循环。

DataTable profiles = DB.ListProfiles();
// CS8600 warning here
//               v
foreach (DataRow r in profiles.Rows)
{
    // processing code here
}


static public DataTable ListProfiles()
{
    DataTable t = new DataTable();
    using (SqlConnection conn = new SqlConnection(connString))
    {
        conn.Open();
        using (SqlCommand cmd = conn.CreateCommand())
        {
            cmd.CommandText = "SELECT * FROM [Table]";
            using (SqlDataAdapter sda = new SqlDataAdapter(cmd))
                sda.Fill(t);
        }
    }

    return t;
}

在本例中,r 有编译器警告。

将 null 文字或可能的 null 值转换为不可为 null 的类型。

我知道需要检查空值等。我的问题是有没有人想出如何使用这个新功能让编译器意识到profilesprofiles.Rows 都不会为空? ListProfiles 中的 t 变量绝对不会返回任何结果,但这不会使 Rows 为空,对吗?

如果我像这样使用 null-coalescing 运算符 ??profiles.Rows ?? ... 并且警告会消失,但我无法弄清楚它之后的实际工作是什么。

我也尝试过使用 !来自How to suppress Possible Null Reference warnings 的运算符,但这没有效果。警告仍然存在。虽然这适用于其他类型,但它似乎不适用于 DataRowCollection

我已经尝试了null 检查的各种位置,但似乎只有明确的代码内抑制有任何效果。

【问题讨论】:

标签: c# c#-8.0


【解决方案1】:

可空值是r,而不是编译器正确识别的profilesprofiles.Rows。只需将其声明为可空,然后在循环中处理空检查:

foreach (DataRow? r in profiles.Rows)
{
    if(r == null) 
        continue;
    // ...
}

原因是DataRowCollection(这是数据表上Rows属性的类型)是一个非泛型可枚举。这就是您使用 .NET 1.0 API 所获得的。

编译器认为非泛型可枚举项的类型为object?,而不是object(或更准确地说,IEnumerator.Currentobject?),因为集合中的任何此类项都可能为空,并且没有泛型将项目限制为不可为空的值。

由于指定foreach 变量的类型只是为您插入一个强制转换,最终结果是您需要将变量本身声明为可为空的,因为您不能安全地将可空值转换为不可为空的值。

【讨论】:

  • 谢谢。这很有意义。如果这不仅仅是一个超级简单的控制台应用程序,我会考虑使用 DataTable 以外的其他东西,但这还不是一个足够大的项目。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-06-25
相关资源
最近更新 更多