#vb.net
#vb.net
Вопрос:
Я создаю программу, которая рассчитывает ежемесячный счет за электроэнергию на основе использования. Коды не аккуратны и выглядят не очень … лаконично, но это работает. Я попытался использовать массив (еще не изучил это в своем курсе), потому что, когда я искал ответы, массивы обычно были решением проблемы. Однако, когда я использую его в своем коде, он вычисляет только для второго оператора, например, если у меня есть If...Else If
, он будет проверять Else If
и игнорировать только начальный If
.
Я создал еще один проект, похожий на проблему. Как вы увидите ниже, месяц длится только до мая, и я должен довести его до октября…
Option Strict On
Public Class Form1
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim marTA, aprTA, mayTA As Single
Dim mar, apr, may As Decimal
Decimal.TryParse(TextBox1.Text, mar) : Decimal.TryParse(TextBox2.Text, apr)
Decimal.TryParse(TextBox3.Text, may)
Select Case True
Case mar = 0
marTA = 3D (3D * 0.06)
TextBox4.Text = marTA.ToString("C2").Replace("$", "RM ")
Case mar >= 1 And mar < 201
marTA = CSng(mar * 0.109)
TextBox4.Text = marTA.ToString("C2").Replace("$", "RM ")
Case mar >= 201 And mar < 301
marTA = CSng((200 * 0.109) ((mar - 200) * 0.153))
TextBox4.Text = marTA.ToString("C2").Replace("$", "RM ")
Case mar >= 301 And mar < 601
marTA = CSng((200 * 0.109) (100 * 0.153) ((mar - 300) * 0.172))
TextBox4.Text = marTA.ToString("C2").Replace("$", "RM ")
Case mar >= 601 And mar < 901
marTA = CSng((200 * 0.109) (100 * 0.153) (300 * 0.172) ((mar - 600) * 0.182))
TextBox4.Text = marTA.ToString("C2").Replace("$", "RM ")
Case mar >= 901
marTA = CSng((200 * 0.109) (100 * 0.153) (300 * 0.172) (300 * 0.182) ((mar - 900) * 0.215))
TextBox4.Text = marTA.ToString("C2").Replace("$", "RM ")
End Select
Select Case True
Case apr = 0
aprTA = 3 (3 * 0.06)
TextBox4.Text = aprTA.ToString("C2").Replace("$", "RM ")
Case apr >= 1 And apr < 201
aprTA = CSng(apr * 0.109)
TextBox4.Text = aprTA.ToString("C2").Replace("$", "RM ")
Case apr >= 201 And apr < 301
aprTA = CSng((200 * 0.109) ((apr - 200) * 0.153))
TextBox4.Text = aprTA.ToString("C2").Replace("$", "RM ")
Case apr >= 301 And apr < 601
aprTA = CSng((200 * 0.109) (100 * 0.153) ((apr - 300) * 0.172))
TextBox4.Text = aprTA.ToString("C2").Replace("$", "RM ")
Case apr >= 601 And apr < 901
aprTA = CSng((200 * 0.109) (100 * 0.153) (300 * 0.172) ((apr - 600) * 0.182))
TextBox4.Text = aprTA.ToString("C2").Replace("$", "RM ")
Case apr >= 901
aprTA = CSng((200 * 0.109) (100 * 0.153) (300 * 0.172) (300 * 0.182) ((apr - 900) * 0.215))
TextBox4.Text = aprTA.ToString("C2").Replace("$", "RM ")
End Select
Select Case True
Case may = 0
mayTA = 3 (3 * 0.06)
TextBox4.Text = mayTA.ToString("C2").Replace("$", "RM ")
Case may >= 1 And may < 201
mayTA = CSng(may * 0.109)
TextBox4.Text = mayTA.ToString("C2").Replace("$", "RM ")
Case may >= 201 And may < 301
mayTA = CSng((200 * 0.109) ((may - 200) * 0.153))
TextBox4.Text = mayTA.ToString("C2").Replace("$", "RM ")
Case may >= 301 And may < 601
mayTA = CSng((200 * 0.109) (100 * 0.153) ((may - 300) * 0.172))
TextBox4.Text = mayTA.ToString("C2").Replace("$", "RM ")
Case may >= 601 And may < 901
mayTA = CSng((200 * 0.109) (100 * 0.153) (300 * 0.172) ((may - 600) * 0.182))
TextBox4.Text = mayTA.ToString("C2").Replace("$", "RM ")
Case may >= 901
mayTA = CSng((200 * 0.109) (100 * 0.153) (300 * 0.172) (300 * 0.182) ((may - 900) * 0.215))
TextBox4.Text = mayTA.ToString("C2").Replace("$", "RM ")
End Select
End Sub
End Class
Проектный вид:
Ответ №1:
В программировании есть аббревиатура DRY. Это означает «Не повторяйся». Для этого есть несколько причин…
- Легче отлаживать.
- Легче изменить — только одно место вместо нескольких.
- Легче читать и понимать.
- Меньше подвержен ошибкам. Если вы попытаетесь написать один и тот же код несколько раз, вы допустите ошибку при переписывании.
Есть несколько способов добиться DRY. Одним из них является перенос повторяющегося кода в отдельную функцию. Смотрите GetUsageCharge
пример этого.
Другой способ — создать коллекцию похожих объектов. Затем используйте цикл, чтобы применить повторяющийся код к каждому элементу в коллекции. Смотрите TextBoxes
и For Each
.
Private Function GetUsageCharge(usage As Integer) As Decimal
Select Case usage
Case 0
Return CDec(3 (3 * 0.06))
Case 1 To 200
Return CDec(usage * 0.109)
Case 201 To 300
Return CDec((200 * 0.109) ((usage - 200) * 0.153))
Case 301 To 600
Return CDec((200 * 0.109) (100 * 0.153) ((usage - 300) * 0.172))
Case 601 To 900
Return CDec((200 * 0.109) (100 * 0.153) (300 * 0.172) ((usage - 600) * 0.182))
Case >= 901
Return CDec((200 * 0.109) (100 * 0.153) (300 * 0.172) (300 * 0.182) ((usage - 900) * 0.215))
End Select
Return 0
End Function
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim TotalCost As Decimal
Dim usage As Integer
Dim TextBoxes As New List(Of TextBox) From {TextBox1, TextBox2, TextBox3}
For Each tb In TextBoxes
If Integer.TryParse(tb.Text, usage) Then
TotalCost = GetUsageCharge(usage)
End If
Next
TextBox4.Text = TotalCost.ToString("C2").Replace("$", "RM ")
End Sub
Как вы можете видеть, этот код намного проще, меньше переменных и т. Д.
Примечание: вы можете избавиться от .Replace("$", "RM ")
, если добавите…
CultureInfo.DefaultThreadCurrentCulture = New CultureInfo("ms-MY")
в Form.Load
Комментарии:
1. Это работает чудесно! Однако есть ошибка — общая стоимость будет постоянно увеличиваться, если пользователь продолжает нажимать на кнопку, отсюда и мои беспорядочные коды. Именно поэтому я разделяю их, чтобы избежать этой проблемы, но это уже другой вопрос, и с этим можно разобраться. Спасибо @Mary
2. TotalCost — это локальная переменная, которая начинается с 0 при каждом нажатии кнопки.
3. Боже мой, я тупой.. Я объявляю это как
Public
потому, что у меня есть еще одно групповое поле для суммирования общей стоимости за каждый месяц, а также для добавления их в список для печати квитанции. Прошу прощения, моя вина.