Ошибка «Преобразование из строки в десятичный тип недопустимо»

#.net #vb.net #visual-studio #winforms

#.net #vb.net #visual-studio #winforms

Вопрос:

Я использую Microsoft Visual Studio professional 2019 версии 16.6.2.

Я создал простой калькулятор с использованием Windows forms. Предполагается, что калькулятор позволяет пользователю нажимать на цифровые кнопки, а также кнопки для различных операторов, а затем отображать результат в текстовом поле после нажатия кнопки = . Калькулятор также имеет десятичную точку, чтобы помочь вычислить десятичное число.

Однако я получаю сообщение об ошибке «преобразование из строки в десятичный тип недопустимо» всякий раз, когда я пытаюсь вычислить десятичные числа.

Я все еще студент и не очень разбираюсь в продвинутом программировании. Если возможно, пожалуйста, постарайтесь, чтобы ваши предложения были как можно более простыми.

 Public Class Form1
    Dim firstNum As Decimal
    Dim secondNum As Decimal
    Dim operations As Integer
    Dim operator_Selector As Boolean = False
    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load

    End Sub

    Private Sub Button2_Click(sender As Object, e As EventArgs) Handles btn2.Click
        If txtDisplay.Text <> "0" Then
            txtDisplay.Text  = "2"
        Else
            txtDisplay.Text = "2"
        End If
    End Sub

    Private Sub btn1_Click(sender As Object, e As EventArgs) Handles btn1.Click
        If txtDisplay.Text <> "0" Then
            txtDisplay.Text  = "1"
        Else
            txtDisplay.Text = "1"
        End If
    End Sub

    Private Sub btn3_Click(sender As Object, e As EventArgs) Handles btn3.Click
        If txtDisplay.Text <> "0" Then
            txtDisplay.Text  = "3"
        Else
            txtDisplay.Text = "3"
        End If
    End Sub

    Private Sub btn4_Click(sender As Object, e As EventArgs) Handles btn4.Click
        If txtDisplay.Text <> "0" Then
            txtDisplay.Text  = "4"
        Else
            txtDisplay.Text = "4"
        End If
    End Sub

    Private Sub btn5_Click(sender As Object, e As EventArgs) Handles btn5.Click
        If txtDisplay.Text <> "0" Then
            txtDisplay.Text  = "5"
        Else
            txtDisplay.Text = "5"
        End If
    End Sub

    Private Sub btn6_Click(sender As Object, e As EventArgs) Handles btn6.Click
        If txtDisplay.Text <> "0" Then
            txtDisplay.Text  = "6"
        Else
            txtDisplay.Text = "6"
        End If
    End Sub

    Private Sub btn7_Click(sender As Object, e As EventArgs) Handles btn7.Click
        If txtDisplay.Text <> "0" Then
            txtDisplay.Text  = "7"
        Else
            txtDisplay.Text = "7"
        End If
    End Sub

    Private Sub btn8_Click(sender As Object, e As EventArgs) Handles btn8.Click
        If txtDisplay.Text <> "0" Then
            txtDisplay.Text  = "8"
        Else
            txtDisplay.Text = "8"
        End If
    End Sub

    Private Sub btn9_Click(sender As Object, e As EventArgs) Handles btn9.Click
        If txtDisplay.Text <> "0" Then
            txtDisplay.Text  = "9"
        Else
            txtDisplay.Text = "9"
        End If
    End Sub

    Private Sub btn0_Click(sender As Object, e As EventArgs) Handles btn0.Click
        If txtDisplay.Text <> "0" Then
            txtDisplay.Text  = "0"

        End If
    End Sub

    Private Sub btnClear_Click(sender As Object, e As EventArgs) Handles btnClear.Click
        txtDisplay.Text = "0"
    End Sub

    Private Sub btnPoint_Click(sender As Object, e As EventArgs) Handles btnPoint.Click
        If Not (txtDisplay.Text.Contains(".")) Then
            txtDisplay.Text  = "."
        End If
    End Sub

    Private Sub btnadd_Click(sender As Object, e As EventArgs) Handles btnadd.Click
        firstNum = txtDisplay.Text
        txtDisplay.Text = "0"
        operator_Selector = True
        operations = 1

    End Sub

    Private Sub btnEqual_Click(sender As Object, e As EventArgs) Handles btnEqual.Click
        If operator_Selector = True Then
            secondNum = txtDisplay.Text

        End If

        If operations = 1 Then
            txtDisplay.Text = firstNum   secondNum
        End If

        If operations = 2 Then
            txtDisplay.Text = firstNum - secondNum
        End If

        If operations = 3 Then
            secondNum = txtDisplay.Text
            txtDisplay.Text = firstNum * secondNum
        End If



        If operations = 4 Then
            If secondNum = 0 Then
                txtDisplay.Text = "ERROR! CANNOT DIVIDE BY 0"

            Else

                txtDisplay.Text = firstNum / secondNum
            End If
        End If

        operator_Selector = False
    End Sub

    Private Sub btnSubtract_Click(sender As Object, e As EventArgs) Handles btnSubtract.Click
        firstNum = txtDisplay.Text
        txtDisplay.Text = "0"
        operator_Selector = True
        operations = 2

    End Sub

    Private Sub btnMultiply_Click(sender As Object, e As EventArgs) Handles btnMultiply.Click
        firstNum = txtDisplay.Text
        txtDisplay.Text = "0"
        operator_Selector = True
        operations = 3

    End Sub

    Private Sub btnDivide_Click(sender As Object, e As EventArgs) Handles btnDivide.Click
        firstNum = txtDisplay.Text
        txtDisplay.Text = "0"
        operations = 4
        operator_Selector = True
    End Sub
End Class
 

Комментарии:

1. Вы можете остановить отладчик в точке исключения и посмотреть, какое значение пытается преобразовать. И если вы включите OPTION STRICT , вы внезапно увидите, что выполняете неявные преобразования в десятичный тип, не выполняя никакой проверки. Имейте в виду, что, учитывая способ, которым вы это создали, нет необходимости фактически использовать значение в текстовом поле для выполнения вычисления, вы можете хранить числа внутри

2. Вы работаете со строками. Такие вещи, как secondNum = 0 не будут работать, поскольку secondNum это строка. Вы должны сначала преобразовать их в Integer или Decimal , прежде чем работать с ними, как если бы они были фактическими числами.

Ответ №1:

Вы объявили firstNum и secondNum как Decimal (числа), что правильно.

Text Свойство текстовых полей — a String .

.NET не хочет автоматически преобразовывать String значение в a Decimal , потому что, вообще говоря, это преобразование неверно определено. Это зависит от вашей культуры: например, какой у вас разделитель тысяч? Это может легко завершиться ошибкой, если строка не представляет число, например "ABC" . Также может произойти сбой или потеря точности, если строка содержит больше цифр, чем Decimal может хранить.

Таким образом, в основном строки типа firstNum = txtDisplay.Text и secondNum = txtDisplay.Text присваивают String значение Decimal переменной, и это то, что язык запрещает.

Вам нужно будет использовать функцию, которая выполняет это преобразование за вас.

Поскольку вы используете VB.NET вы можете использовать CDec (расшифровывается как Convert to Decimal) , который более или менее преобразует что-либо в a Decimal .

 firstNum = CDec(txtDisplay.Text)
 

CDec специфично для VB.NET хотя. Стандартная функция из библиотеки базовых классов (которую вы могли бы использовать, например, в C #) Decimal.Parse — это преобразование строки в десятичное число. Если вы посмотрите на документацию, вы обнаружите, что она может принимать дополнительные параметры, которые управляют тем, как выполняется синтаксический анализ (язык, параметры номера и т. Д.)

 firstNum = Decimal.Parse(txtDisplay.Text)
 

В качестве дополнительного совета вы могли бы действительно уменьшить количество обработчиков кликов, если бы вы поместили число, которое они представляют, в свойство control Tag .

Первым параметром sender в обработчике щелчка является элемент управления, на который был нажат. Итак, предполагая, что вы помещаете значения "0" , "1" , … в Tag свойство каждой кнопки, вы можете повторно использовать один и тот же обработчик щелчков для всех из них, выполнив что-то вроде txtDisplay.Text = sender.Tag .