2008-09-11

Narrowing & Widening Conversion Gotcha

What is Narrowing & Widening Conversion
Basically there are two type of conversions, Narrowing conversion and Widening conversion. Both these conversions comes into picture whenever type conversion occurs. An important consideration with a type conversion is whether the result of the conversion is within the range of the destination data type. A widening conversion changes a value to a data type that can accommodate any possible value of the original data. Converting from an Integer to a Long is a widening conversion. A narrowing conversion changes a value to a data type that might not be able to hold some of the possible values. Converting from a Long to a Integer is a narrowing conversion.

When does it occurs
Narrowing conversions are done by default i.e. implicitly by the .NET compiler. The compiler doesn't do widening conversions implicitly for you. When you assign a Long variable's value to a Integer variable narrowing conversion is done by default. The compiler automatically treats the number as Integer. But when assign a Integer value to a Long variable, compiler doesn't treat it as a long data type value. Having said that, you need to explicitly tell the compiler that your number is a Long.

Gotcha
Sometimes things can go wrong without your knowledge while these conversions are involved. Lets have a look at following code segment:

Lets consider that you have a form with a ComboBox control dropped on it.

Public Class Form1

Public Class cListItem
Private m_id As Integer
Private m_text As String

Public Sub New( _
ByVal id As Integer, _
ByVal text As String _
)
Me.m_id = id
Me.m_text = text
End Sub

Public Property ID() As Long
Get
Return m_id
End Get
Set(ByVal value As Long)
m_id = value
End Set
End Property

Public Property Text() As String
Get
Return m_text
End Get
Set(ByVal value As String)
m_text = value
End Set
End Property
End Class

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

Dim items As cListItem() = New cListItem(3) {}

items(0) = New cListItem(1, "Test 1")
items(1) = New cListItem(2, "Test 2")
items(2) = New cListItem(3, "Test 3")
items(3) = New cListItem(4, "Test 4")

ComboBox1.Items.AddRange(items)
ComboBox1.DataSource = items
ComboBox1.ValueMember = "ID"
ComboBox1.DisplayMember = "Text"
End Sub

Private Sub Button1_Click( _
ByVal sender As System.Object, _
ByVal e As System.EventArgs _
) Handles Button1.Click

ComboBox1.SelectedValue = 2
End Sub

End Class
Above code populates the ComboBox with some values. If you click the button it should select the second item in the ComBox, but it doesn't. Why?

When you assign a numeric value '2' to the 'SelectedValue' property of the ComboBox at line "ComboBox1.SelectedValue = 2", the compiler automatically treats the number 2 as an Integer. Since all the combo box items are Long objects, it doesn't find a match. So nothing is selected and you end up with a blank combo box.

Solution
The compiler doesn't do widening conversions implicitly for you, so you have to do the conversion explicitly.
' Explicitly convert the Integer to Long
ComboBox1.SelectedValue = 2L
So the moral of the story is to make a practice of converting values to proper types while doing type conversions.

No comments: