Why is my public variable not behaving as expected? - vb.net

Public Class Form1
Public diameter As Integer
Public radius As Decimal = diameter / 2
Private Sub TxtRadius10_TextChanged(sender As Object, e As EventArgs) Handles TxtRadius10.TextChanged, TxtDiameter10.TextChanged
diameter = TxtDiameter10.Text
TxtRadius10.Text = radius
End Sub
End Class
The value in TxtRadius10 keeps coming back 0 when it should be 5 (The text in TxtDiameter10 box is 10 and locked). I know diameter is initializing because if I set TxtRadius10.Text = diameter/2, it will come back 5.

This isn't doing what you think it's doing:
Public radius As Decimal = diameter / 2
The radius variable doesn't hold a reference to the diameter variable for future calculations. This assignment statement calculates it once with the current values and places the result in radius. The current value of diameter is:
Public diameter As Integer
Well, it's unassigned. So it's defaulting to 0. And 0 / 2 is 0. So radius is being initialized to 0, and it's never assigned again in the code. So it will always be 0.
If you want to dynamically calculate the value every time it's accessed, make it a property:
Public Property radius As Decimal
Get
Return diameter / 2
End Get
End Property
Now any reference to radius will run the Get logic whenever it's accessed and re-calculate the value on the fly.

You've got yourself an unintended loop.
When you change the value of TxtRadius10.Text in the TxtRadius10_TextChanged event, it fires off the event again. Since diameter starts off as 0 (the default value of an integer), the radius value starts off as 0 (0 / 2).
You should also know that Radius is not going to update when you update diameter. You've just set an initial value for it. You've got to recalculate the radius whenever diameter changes.

You're declaring radius = diameter/ 2
However diameter isn't defined when it comes across this statement.
Define diameter first before defining radius

Related

Implication of marking an instance of a structure as ReadOnly

In the below code I am not understanding the role played by ReadOnly. I elaborate my question below:
Structure Mutable
Private x As Integer
Public Function Mutate() As Integer
x = x + 1
Return x
End Function
End Structure
Module Module1
Public ReadOnly m As Mutable 'Statement 1
Sub Main()
Console.WriteLine(m.Mutate()) ' 1 Statement 2
Console.WriteLine(m.Mutate()) ' 1
Console.WriteLine(m.Mutate()) ' 1
Console.ReadLine()
End Sub
End Module
How the control behaves if the ReadOnly keyword was not there:
Statement 1 would read as: Public m As Mutable
Upon execution of statement 1, an instance “m” gets created in the stack memory which is large enough to fit an integer type value “x” in it. The default value of x is 0
m.Mutate() gets executed the first time. The control calls the function Mutate() where x = x+1 gets executed which increases the value of x by 1
The value of x = 1 is returned to the function Mutate() which is then displayed.
Steps 3 and 4 get repeated for the next two times when Mutate() function is called. The key point is that the value of x increases from 0 to 1, then from 1 to 2 and then finally to 3.
What is the difference when we add the ReadOnly keyword?
m.mutate() gets executed the first time which increases the value of x from 0 to 1. This is returned and “1” gets printed
But when the control shifts to the next line i.e. statement 2,and after the Mutate() function is called again I see from a break-point analysis that it is then the value of x is reset to 0 from 1. The function Mutate gets executed which increases the value again from 0 to 1 which gets printed. This is the main difference.
My Question:
Why does the presence of ReadOnly keyword reset the value of x to 0 everytime the function Mutate is called? In this case, “m” is a local variable storing an instance of the structure. When an instance of a structure is declared as ReadOnly in VB.Net what is the implication? In such cases, should I understand the role of ReadOnly as “write once and reset if called again”? Can someone please explain the point.
My confusion stems from the fact that ReadOnly in VB.Net can be only used on Properties and Member Variables (Fields). When that is the case, their values can be set in the constructor of that structure/class or at declaration. But here “m” stores an instance. So what changes are being introduced when ReadOnly is being used on an instance?
In short how should I understand why using the ReadOnly keyword gives the output as “1 1 1”?

Is there a way to generate a random number using a Minimum and Maximum value using Single in VB.Net?

I'm looking for a random number generator that I can use to alter the size of a picture box on my form. Currently, I have this solution found here on StackOverflow:
Public Function GetRandomNumber(ByVal Min As Integer, ByVal Max As Integer) As Integer
Static lcGenerator As System.Random = New System.Random()
Return lcGenerator.Next(Min, Max)
End Function
As it stands, the function will generate a random integer between the range specified. This is great, but I am noticing that often the picture box doesn't change in size with a decent amount of variation. The following code shows how I am calculating variance in size:
Dim lcModifier As Decimal = (GetRandomNumber(-20, 11) * 0.01)
pbForeground.Width = CInt((0.4 - lcModifier) * pbBackground.Width)
pbForeground.Height = CInt((0.4 - lcModifier) * pbBackground.Height)
The idea is that I generate a random number between -20 and 11. This would yield a 20% increase or 10% decrease, as the minimum is inclusive but the maximum is exclusive, and I am subtracting the modifier.
I had the idea to use a Single value in place of the integer value. The Single type gave me more "room" away from 0 than a Double would, but the Next method only uses Integer values, and we're back to my initial problem.
The NextDouble method works differently to the Next method, and I am unable to specify Min and Max values, nor can I generate a negative value.
Is there any way I can generate a value using Minimum and Maximum bounds that is not close to zero?
Thanks,
sunnyCr
The NextDouble return a percentage. You just need to multiply by the range of value and then translate to the desired starting position.
Function GetRandomNumber(ByVal low As Double, high As Double) As Double
Static rng As New Random
Return (rng.NextDouble() * (high - low)) + low
End Function

Multiplying singles and decimals

If btnTotalCost.Text = "Calculate total cost" Then
btnTotalCost.Text = "Refresh"
Else
btnTotalCost.Text = "Calculate total cost"
End If
Dim dHamSandwich As Decimal = 1.35
Dim sHamQuantity As Single
txtHam.Text = sHamQuantity
dTotalSandwichCost = dHamSandwich * sHamQuantity
If btnTotalCost.Text = "Refresh" Then
MsgBox(dTotalSandwichCost)
End If
When I calculate the message box that appears shows the number 0. I want it to multiply the quantity and the cost to give the total cost of the sandwich. For example, if I input 2 into the quantity text box, it should multiply 1.35 by 2.
first of all you should specify EXACTLY what you use. As the comment of Ste Griffiths suggest, it seems to be VB.NET.
Secondly please start learning the usage of data types and variables.
You do
Dim dHamSandwich As Decimal = 1.35 ' <- this is fine
Dim sHamQuantity As Single '<- this is an uninitialised Single variable, in .net it will be set to 0
txtHam.Text = sHamQuantity '<- then you assign the unassigned Single variable to your Textbox's property Text(which requires a string)
'That means it will implicitly convert the Single to String and then "show" it in the textbox (which will be 0)
dTotalSandwichCost = dHamSandwich * sHamQuantity 'here you multiply 1.35 * 0. Sure it will be 0. Also you multiply a decimal with a single data type which will implicitly convert the latter (if I remember correctly)
The question for me here is. Why do you even use Single and Decimal? You can use either one. But the main problem is actually not even the data types, but the assignment.

Restrict numeric input vb property grid

I have a variable that can only be set to certain numbers (integers and decimals) and that gets assigned by the user using a property grid. What I want is something that behaves like an Enum, where the users can select from a a drop down list of acceptable values. However enums don't see to support non integer numeric input. Any ideas?
Ended up doing get/set and just changing the value if it's outside the acceptable range.
<DataMember()>
<DisplayName("Fisheye Angle")>
<Description("This value indicates the angle used in the fisheye view, if it is enabled. The acceptable range is 45 to 360 degrees with 180 degrees being the default. ")>
<DefaultValue(180)>
Public Property FisheyeAngle As Double
Get
Return _FisheyeAngle
End Get
Set(value As Double)
If value < 45 Then
_FisheyeAngle = 45
ElseIf value > 360 Then
_FisheyeAngle = 360
Else
_FisheyeAngle = value
End If
End Set
End Property

MPG calculator not giving correct answer

I am trying to create a MPG calculator in Visual Basic, but it only calculates in whole numbers not decimals. When I input 10 into the gallons section and 375 into the miles section, the calculator only calculates 37 not 37.5.
Public Class Form1
Private Sub btnCalculateMpg_Click(sender As Object, e As EventArgs) Handles btnCalculateMpg.Click
'Declare variables for the calculation.
Dim intMpg As Integer
lblMpgCalculated.Text = String.Empty
Try
'Calculate and display Miles per Gallon.
intMpg = CInt(txtMiles.Text) \
CInt(txtGallons.Text)
lblMpgCalculated.Text = intMpg.ToString("N")
Catch
'Error Message.
MessageBox.Show("All input must be valid numeric values.")
End Try
End Sub
intMpg should not be an integer if you don't want to receive a result that's an integer. You may want to use a Double, in which case the line where you declare intMpg would be:
Dim intMpg As Double
You also should use the / operator for division, not the \ operator, since the latter performs integral division, as explained here.
So, the line where you perform the division should be:
intMpg = CInt(txtMiles.Text) / CInt(txtGallons.Text)
If you perform these changes, intMpg would be a misleading name (since it's not an integer, even though the name makes it sound like it is), so you should change it to something else like milesPerGallon.
Integers are only whole numbers. Storing the result of a division in an Integer will do an integer division, which means your result will also be an integer and the decimal will get truncated. To get decimals, you should declare your result variable as a Double.