【问题标题】:Visual Basic - system.nullReferenceExceptionVisual Basic - system.nullReferenceException
【发布时间】:2014-11-01 10:28:39
【问题描述】:

所以在编程方面我还是个新手,因此我使用 Visual Basic。我反复引发此异常,但是 vb 所说的具有未分配值的变量已在我的代码中被赋予了值。谁能指出我哪里出了问题?

编辑:还有一些细节:文件存在,我可以使用 ReadLine 方法从中读取,但我需要拆分字段以便比较分数并获得最高的 2 个分数

Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load

    Dim srdFile As System.IO.StreamReader
    Dim strLine As String
    Dim strField(1) As String
    Dim strName() As String
    Dim strScore() As String
    Dim i = 0

    srdFile = New System.IO.StreamReader("HighScores.dat")
    rtbOut.AppendText("HighScores:" & vbNewLine & vbNewLine)

    Do Until srdFile.Peek() = -1

            strLine = srdFile.ReadLine()
            strField = strLine.Split(",")

            strName(i) = strField(0)
            strScore(i) = strField(1)

            rtbOut.AppendText(strName(i) & ", " & strScore(i) & vbNewLine)

            i = i + 1

    Loop
End Sub

【问题讨论】:

  • 什么变量未赋值?顺便说一句,我建议默认将Option Strict 设置为On
  • 欢迎来到 Stack Overflow!几乎所有NullReferenceException 的情况都是一样的。请参阅“What is a NullReferenceException in .NET?”获取一些提示。

标签: vb.net nullreferenceexception


【解决方案1】:

以下两个数组永远不会初始化:strNamestrScore

我不知道逻辑,但一种方法是使用List(Of String),而不需要首先获得正确的大小并且可以调整大小。我还将使用Using-statement 正确处理流:

Using srdFile As New System.IO.StreamReader("HighScores.dat")
    Dim strLine As String
    Dim strField(1) As String
    Dim strName As New List(Of String)
    Dim strScore As New List(Of String)
    Dim i = 0

    rtbOut.AppendText("HighScores:" & vbNewLine & vbNewLine)
    Do Until srdFile.Peek() = -1
        strLine = srdFile.ReadLine()
        strField = strLine.Split(","c)
        strName.Add(strField(0))
        strScore.Add(strField(1))

        rtbOut.AppendText(strName(i) & ", " & strScore(i) & vbNewLine)
        i += 1
    Loop
End Using

旁注:我建议默认将Option Strict 设置为On


顺便说一句,这是一种完全不同的方法,但使用LINQ

Dim lines = From line In IO.File.ReadLines("HighScores.dat")
            Where Not String.IsNullOrWhiteSpace(line)
            Let fields = line.Split(","c)
            Let name = fields.First()
            Let score = fields.Last()
            Select String.Format("{0}, {1}", name, score)
rtbOut.Text = String.Join(Environment.NewLine, lines)

我觉得这更具可读性。

【讨论】:

  • 我尝试编译您的代码,但出现构建错误。我只是不明白为什么变量被读取为空,循环肯定正在执行,因为我尝试将“测试”直接从文件输出到 rtb。问题是将文件拆分为单独的数组。它们被赋予了一个值,那么为什么我会得到一个空异常?
  • @keelan1234:你得到什么构建错误?它至少应该编译。您使用的是什么框架(或 VisualStudio 版本)?您已经声明了这些数组,但从未初始化它们,这就是为什么它们仍然是Nothing,当您尝试访问它们时会引发异常(例如strName(i))。你可以这样初始化它:Dim strName(1) As String。但是数组只能包含两个字符串。我的第二种方法有效吗?
  • 我不懂你的代码,不是我是怎么学的,所以如果可能的话,我想使用我的代码。我正在使用 VS 2010,我认为在此期间我只是将数组的大小设置为 2,而不是存储所有分数,我可以检查提交的分数是否高于当前的 2 个高分,如果没有,则可以将其丢弃。
【解决方案2】:

在使用数组之前,您需要在计算机内存位置分配一个固定的数组大小。您可以通过使用数组元素的数量初始化一个数组来做到这一点。在您的代码中,您在使用它们之前没有为 strName() 和 strScore() 分配任何内存,因此代码将引发异常。

Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    Dim srdFile As System.IO.StreamReader
    Dim strLine As String
    Dim strField(1) As String
    Dim strName(10) As String ''fixed size array (Using List(Of T) is a better option)
    Dim strScore(10) As String ''fixed size array (Using List(Of T) is a better option)
    Dim i = 0

    srdFile = New System.IO.StreamReader("HighScores.dat")
    rtbOut.AppendText("HighScores:" & vbNewLine & vbNewLine)

    Do Until srdFile.Peek() = -1

        strLine = srdFile.ReadLine()
        strField = strLine.Split(",")

        strName(i) = strField(0)
        strScore(i) = strField(1)

        rtbOut.AppendText(strName(i) & ", " & strScore(i) & vbNewLine)

        i = i + 1

    Loop
End Sub

您还可以创建动态数组。请关注 Stackoverflow 上的 Resizing an array at runtime in VB.NET 了解动态数组。

【讨论】:

  • 请考虑建议使用List(Of T) 而不是调整数组大小。
  • 谢谢安德鲁。我完全同意, List(Of T) 比调整数组大小更好。 List(Of T) 自己处理动态内存分配,节省大量代码。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-09-18
  • 1970-01-01
  • 2014-11-29
  • 2014-07-31
  • 2015-01-09
  • 2019-05-23
相关资源
最近更新 更多