在下面的代码中,如果cmd已经初始化,那么我将确保在引发异常之前关闭所有打开的连接。但是,即使在检查cmd不为null之后,在后续代码行中仍然会收到可能为null的引用警告。

Dim cmd As SqlCommand
Try
    'Do some Stuff
Catch ex As Exception
    If cmd IsNot Nothing AndAlso
       cmd.Connection IsNot Nothing AndAlso              '<- null cmd warning
       cmd.Connection.State = ConnectionState.Open Then  '<- null cmd warning
        cmd.Connection.Close()                           '<- null cmd warning
    End If
    Throw
End Try
我收到以下两个警告(可能来自Resharper,一个来自Visual Studio):
  • 变量'x'可能在访问前未初始化。空引用异常可能在运行时发生。
  • BC42104:在变量'x'被赋值之前被使用。空引用异常可能在运行时导致。

  • 根据Visual Studio Page:

    应用程序的代码中至少有一条可能的路径,该路径在将任何值赋给变量之前先读取一个变量。

    但是我不认为代码中甚至没有一条可能的路径来使用变量而无需初始化。
  • 我犯了一些错误还是这是一个错误?
  • 是否可以禁用此警告?

  • 这是屏幕截图:

    这与这里已经问过的许多类似问题(例如Prevent Resharper “Possible Null Reference Exception” warnings)不同,因为我没有尝试允许使用NullableType,而是已经保证我的变量不为null。

    更新:
    后续问题:为什么?
    无论我的对象是从不初始化还是初始化为Nothing,在两种情况下cmd IsNot Nothing都应解析为False,因此,永远不要执行AndAlso之后的任何操作。
    Dim cmd1 As SqlCommand
    Console.Write(cmd1 IsNot Nothing) 'False
    
    Dim cmd2 As SqlCommand = Nothing
    Console.Write(cmd2 IsNot Nothing) 'False
    
    也许编译器在编译时没有一个很好的方法来保证这一点。

    最佳答案

    您的问题不是您的值为null,而是您的对象根本没有初始化。例如:

        static void Main(string[] args)
        {
            List<int> empty;
    
            if (empty != null)
            {
                Console.WriteLine("no");
            }
        }
    

    将不会编译,因为empty没有值。如果我将代码更改为:
        static void Main(string[] args)
        {
            List<int> empty = null;
    
            if (empty != null)
            {
                Console.WriteLine("no");
            }
        }
    

    它将起作用,因为我的列表现在有一个值,它为null,但仍然存在。

    编辑:对不起,我使用C#而不是VB,这是因为该编辑器非常方便,但是代码正确。
    每次都初始化变量,就不会出错。

    09-16 17:15
    查看更多