在 foreach 中的 DataRow 上转换空文字或可能的空警告

Converting null literal or possible null warning on DataRow in foreach

更新了我的 .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 有编译器警告。

Converting null literal or possible null value to non-nullable type.

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

如果我像这样使用空合并运算符 ??profiles.Rows ?? ... 并且警告会消失,但我无法弄清楚在它之后可以做什么才能真正起作用.

我也试过使用 !来自 的运算符,但这没有任何效果。警告仍然存在。虽然这适用于其他类型,但似乎不适用于 DataRowCollection.

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

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

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

原因是DataRowCollection(数据table上Rows属性的类型)是非泛型可枚举。这就是使用 .NET 1.0 API 的好处。

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

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