变量在被赋值之前已被使用是什么意思? [英] What does it mean by variable has been used before it has been assigned a value?

查看:81
本文介绍了变量在被赋值之前已被使用是什么意思?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我创建这个程序的目的是对numbers.txt"文本文件进行冒泡排序.但是下面粗体的行给我一个变量的错误,它在被赋值之前就被使用了.有人可以帮我吗?我似乎无法弄清楚这一行 numbers2(z) = numbers(z).因为每次我加载这个程序时,它都会在我身上崩溃.我很想有人给我一些帮助

I created this program with the intention of bubble sorting "numbers.txt" textfile. But the line below that is bolded is giving me an error of variable has been used before it has been assigned a value. Can someone help me at this? I seem to cant figure out this line numbers2(z) = numbers(z). Cause every time I load this program, it crashes on me. I would love someone to give me some assistance

 Public Class Form1
    Dim currentLine As String = ""
    Dim data As New System.IO.StreamReader("numbers.txt")
    Dim counter As Integer = 0
    Dim currentValue As Integer
    Dim previousValue As Integer
    Dim nextValue As Integer
    Dim isLoaded As Boolean = False
    Dim numbers As String()
    Dim numbers2 As String()
    Public Sub btnSort_Click(sender As Object, e As EventArgs) Handles btnSort.Click
        If (Not isLoaded) Then
            MessageBox.Show("You have not loaded")
        Else

            For j = 0 To counter
                If (j = 0) Then
                    currentValue = CInt(numbers2(j))
                    nextValue = CInt(numbers2(j + 1))
                    If (currentValue > nextValue) Then
                        numbers2(j + 1) = numbers2(j)
                        numbers2(j) = numbers(j + 1)
                    End If
                ElseIf (j = counter) Then
                    Continue For
                ElseIf (j = counter - 1) Then
                    currentValue = CInt(numbers2(j))
                    previousValue = CInt(numbers2(j - 1))
                    If (currentValue > previousValue) Then
                        'Good
                    ElseIf (currentValue < previousValue) Then
                        numbers2(j - 1) = numbers2(j)
                        numbers2(j) = numbers(j - 1)

                    End If
                Else
                    currentValue = CInt(numbers2(j))
                    previousValue = CInt(numbers2(j - 1))
                    nextValue = CInt(numbers(j + 1))
                    If (currentValue < nextValue) Then
                        'Good
                    ElseIf (currentValue > nextValue) Then
                        numbers2(j + 1) = numbers2(j)
                        numbers2(j) = numbers(j + 1)
                    End If
                    If (currentValue > previousValue) Then
                        'Good
                    ElseIf (currentValue < previousValue) Then
                        numbers2(j - 1) = numbers2(j)
                        numbers2(j) = numbers(j - 1)

                    End If

                End If
            Next

            For k = 0 To counter
                tbOutput.Text += numbers2(k) & vbCrLf
            Next
            For z = 0 To counter
                numbers(z) = numbers2(z)
            Next
        End If
    End Sub

    Public Sub btnLoad_Click(sender As Object, e As EventArgs) Handles btnLoad.Click
        Dim numbers As String() = currentLine.Split(New String() {Environment.NewLine}, StringSplitOptions.None)
        Dim numbers2 As String()

        Do While data.Peek() <> -1
            'Appends currentline with results from data.readline and a new line
            currentLine = currentLine & data.ReadLine() & vbNewLine
            'shows the amount of lines in the file
            counter += 1

        Loop
        'displays content from the file
        tbInput.Text = currentLine
        'sets 

        For z = 0 To counter
            **numbers2(z) = numbers(z)**
        Next

        isLoaded = True
    End Sub

    Private Sub tbOutput_TextChanged(sender As Object, e As EventArgs) Handles tbOutput.TextChanged

    End Sub
End Class

推荐答案

从根本上说,这个问题说明了对变量、对象引用、对象实例和类型之间差异的理解.在您真正了解这些差异之前,您将继续作为一名编码员而奋斗.不要感觉不好;在这里你并不孤单,一旦你突然明白了,一切都会变得容易得多.

Fundamentally, this question speaks to understanding of the differences between variables, object references, object instances, and types. Until you really understand those differences, you will continue to struggle as a coder. Don't feel bad; you're far from alone here, and once you do get this suddenly everything is a whole lot easier.

numbers2 是一个变量.与 .Net 中的所有变量一样,numbers2 具有特定的类型:在这种情况下,字符串数组是一种引用类型.但这与说 numbers2 本身是一个数组不是一回事.一个实际的数组是一个对象的实例,就像所有对象实例都存在于内存中与任何变量分开的地方.然后你必须给出numbers2代码> 变量 对数组对象的引用.引用将变量与对象连接起来.

numbers2 is a variable. Like all variables in .Net, numbers2 has a specific type: in this case, string array, which is a reference type. But that is not the same thing as saying numbers2 is itself an array. An actual array is an instance of an Object, and like all object instances exists off in memory somewhere separate from any variable. You must then give the numbers2 variable a reference to the array object. References connect variables with objects.

引用不是对象,因为可能有很多引用都指向同一个对象.但是没有引用,对象就没有用了,内存会被垃圾收集器回收.引用不是变量,因为一个变量在其生命周期内可能有多个不同的引用分配给它.但是对于分配引用的时间跨度,变量的值就是该引用.一个变量肯定不是(就其本身而言)一个对象.甚至 Form1 变量也只是一个对象引用变量,您可以为其分配一个全新的 Form1 对象实例(VB.Net 允许您使用相同的名称可能令人沮丧,而且我相信默认情况下使用 Windows 窗体执行此操作是许多新程序员在整个类型 vs 引用 vs 对象"领域中造成混淆的根源).

The reference is not the object, because there may be many references all pointing to the same object. But without a reference, an object is useless and the memory will be reclaimed by the garbage collector. The reference is not the variable, because one variable may have several different references assigned to it over its lifetime. But for the span of time the reference is assigned, the value of the variable is that reference. And a variable most certainly is not (by itself) an object. Even the Form1 variable is simply an object reference variable, and you could assign a whole new Form1 object instance to it (that VB.Net allows you to have variables and types with the same name can be frustrating, and I believe doing this by default with Windows forms is the source of much confusion in this whole "types vs reference vs object" area for many new programmers).

分配引用的一种方法是在创建新对象时.当您在同一行看到带有 New 关键字的 Dim 语句时,就会发生这种情况.这也是当您有一个包含下标(大小)的数组的 Dim 语句时会发生的情况,例如 Dim items(4) As StringDim items作为字符串(4).这里的编译器会自动创建数组对象.但是如果你不包括数组的大小(Dim numbers2() As String),编译器还没有足够的信息来创建数组,因为它不知道有多大对象需要.所以现在你有一个对象引用变量,但还没有分配给它的对象实例.

One way to assign a reference is while creating a new object. This is what happens when you see a Dim statement with the New keyword on the same line. This is also what happens when you have a Dim statement for array that includes a subscript (size), such as Dim items(4) As String or Dim items As String(4). The compiler here will automatically create the array object. But if you don't include a size for an array (Dim numbers2() As String), the compiler does not yet have enough information to create the array, because it doesn't know how big the object needs to be. So now you have an object reference variable, but there's no object instance assigned to it yet.

现在我们知道的足够多,可以开始调试这个程序了.

Now we know enough to begin debugging this program.

我们将从 Load 方法开始.这个方法的开头重新声明了 numbersnumbers2 数组:

We'll start in the Load method. The beginning of this method re-declares the numbers and numbers2 arrays:

Dim numbers As String() = currentLine.Split(New String() {Environment.NewLine}, StringSplitOptions.None)
Dim numbers2 As String()

这意味着该方法正在使用与类顶部定义的数组完全不同的变量,等等,在Sort 方法中,没有数据;数组仍然为空/无.

This means the method is working with completely different variables from the arrays defined at the top of the class, and so later on, in the Sort method, there's no data; the arrays are still null/Nothing.

此外,numbers2 的声明没有赋值.它只是创建一个空数组引用.这与具有 0 个元素的数组对象不同.这里还没有任何数组对象.这就是导致所指示行出现异常的原因.您正在尝试在将 任何 对象分配给它之前使用 numbers2 引用变量.

Additionally, the declaration for numbers2 doesn't assign anything. It just creates an empty array reference. This is different than having an array object with 0 elements. There is no array object here at all yet. This is what causes the exception on the line indicated. You are trying to use a numbers2 reference variable before any object has been assigned to it.

为了解决问题,我首先要做的是将事件处理程序与有效的代码分开;尽可能将事件代码限制在处理读写控制属性的语句中.我们将创建一个新的 LoadData() 函数,它接受一个参数并返回一个值.新方法与任何文本框、全局或类变量或控件无关.它只知道如何以最适合数据的格式读取数据:

To fix things, what I would do first of all is separate the event handlers from the code that does work; limit event code as much as possible to the statements the deal with reading and writing control properties. We'll make a new LoadData() function which accepts an argument and returns a value. The new method is not concerned with any textboxes, global or classs variables, or controls. It merely knows how to read the data in the format most appropriate for the data:

Public Function LoadData(fileName As String) As IEnumerable(Of Integer)
     Return File.ReadLines(fileName).Select(Function(line) Integer.Parse(line.Trim()))
End Function

现在现有的Load方法可以调用这个函数了.如果此方法根据最适合您的应用程序而不是单击按钮来处理 Form_Load、Form_Shown、Form_Activated 或类似事件,那就更好了.另外,让我们为 numbers 对象选择一个更好的类型:

Now the existing Load method can call this function. Even better if this method handles the Form_Load, Form_Shown, Form_Activated, or similar event depending on what is most appropriate for your application, rather than a button click. Also, let's choose a better type for our numbers object:

Private numbers As List(Of Integer)

Public Sub Form1_Load(sender As Object, e As EventArgs) Handles Form1.Load
    numbers = LoadData("numbers.txt").ToList()

    tbInput = String.Join("\n", numbers)
End Sub

我们可以通过删除回字符串的转换来提高效率,但该版本需要更多的代码,并且除非您拥有非常大集合,否则它不会产生有意义的差异.

We could make this more efficient by removing a conversion back to string, but that version requires a lot more code, and it's won't make a meaningful difference until you have very large collections.

现在我们来看看排序方法:

Now let's look at the sort method:

 Public Sub btnSort_Click(sender As Object, e As EventArgs) Handles btnSort.Click
    If numbers Is Nothing OrElse numbers.Count = 0 Then
        MessageBox.Show("You have not loaded")
        Return
    End If

    numbers = numbers.OrderBy(Function(n) n).ToList()
    tbOutput.Text = String.Join("\n", numbers)
End Sub

把它们放在一起:

Public Class Form1

    Private numbers As List(Of Integer)

    Public Sub btnSort_Click(sender As Object, e As EventArgs) Handles btnSort.Click
        If numbers Is Nothing OrElse numbers.Count = 0 Then
            MessageBox.Show("You have not loaded")
            Return
        End If

        numbers = numbers.OrderBy(Function(n) n).ToList()
        tbOutput.Text = String.Join("\n", numbers)
    End Sub

    Public Sub Form1_Load(sender As Object, e As EventArgs) Handles Form1.Load
        numbers = LoadData("numbers.txt").ToList()

        tbInput = String.Join("\n", numbers)
    End Sub

    Public Function LoadData(fileName As String) As IEnumerable(Of Integer)
         Return File.ReadLines(fileName).Select(Function(line) Integer.Parse(line.Trim()))
    End Function
End Class

现在我怀疑这是课程作业,您的讲师不希望您使用 OrderBy()Array.Sort().但即使在这种情况下,请遵循 LoadData() 函数中的示例:创建一个与按钮事件处理程序分开的方法,该方法接受一个 IEnumerable(Of Integer) 并返回一个排序IOrderedEnumerable(Of Integer),并使用按钮点击事件处理程序调用此方法.结果将是保留相同基本结构的代码,您仍然只需要一个类级变量.

Now I suspect this is course work, where your instructor does not want you to use OrderBy() or Array.Sort(). But even in that case, follow the example from the LoadData() function: create a method separate from the button event handler which accepts an IEnumerable(Of Integer) and returns a sorted IOrderedEnumerable(Of Integer), and use the button click event handler to call this method. The result will be code that retains this same basic structure, where you still only need the one class-level variable.

这篇关于变量在被赋值之前已被使用是什么意思?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆