Casting Reference Types in Visual Basic .NET

Casting Reference Types in Visual Basic .NET

asting, or converting the value of a token from one type of data to another is common to most (if not all) programming languages. Visual Basic has long had a series of casting functions, such as CStr, CInt, CLong, etc. to allow conversion of one type of variable to another. While the idea of casting is simple and familiar when discussed in the context of a simple variable containing a value (.NET value types), the meaning and behavior of a cast is less clear when discussed in the context of objects.

Casting is the term used to describe the conversion of a value from one data type to another. In principle this is fairly straightforward to most experienced programmers. A String of “12” can be converted to an Integer of 12. A Date value of 12/07/41 can be converted to a String of “12/07/41” or even “December 7, 1941”.

Variables in .NET languages are referred to as “types”, and there are two types that you need to concern yourself with in any .NET language: value types and reference types. Value types are the simpler, or at least the more familiar of the two. Value types include Boolean and numeric values (Float, Long, Double, Integer), Date, and DateTime values. Value types are all based on structures rather than classes. Structures are stored on the memory stack rather than the heap and cannot be subclassed. Integer types are based on the System.Int32 structure, Long types are based on System.Int64, Boolean types are based on System.Boolean, DateTime types are based on System.DateTime, and so forth. The base value type structures derive from System.ValueType, which is in turn derived from System.Object.

Figure 1: The hierarchy of value types and reference types.

Reference types are all derived from the System.Object class, not from the derived System.ValueType. .NET stores reference types on the memory heap, rather than the stack, and include not only what you might think of as objects, that is, instances of your own custom classes (as well as the other couple of thousand .NET classes), but also more complex native data representations such as arrays and strings. Figure 1 illustrates these relationships.

This article discusses how casting reference types actually works, and how you can take advantage of casting when interacting with class instances. Understanding this diagram is important if you want to understand the differences between casting value types and casting reference types.

Implicit and Explicit Casting
.NET languages allow implicit casting of one type to another. For instance, if you assign an Integer value to a variable declared as a Double, you generate neither compiler nor runtime errors:

   Dim a As Integer   a = 125   Dim b As Double   b = a

The reason that this is permissible is that there is no loss of data (no rounding) to perform this cast. Other casts of value types can cause a loss of data, such as when you do the reverse, casting a Double value type as an Integer type. If the Double type is holding a value that includes a fraction, such as 10.25, this value will be rounded to 10 if it is recast as an Integer, losing the fractional portion.

   Dim b As Doubleb = 125.23Dim a As IntegerA = CInt(b)

You can easily see the practical effect of casting one data type to another, especially when it results in a change in the value being stored. Less obvious is whether or not the underlying structure being used to store the value is being changed. One might assume that this is the case, but how do you confirm this? (See Sidebar: Preventing Implicit Casts)

Both value type structures and object-based classes inherit from System.Object, and therefore inherit an implementation of the GetType() method that allows you to determine what kind of type you’re dealing with.

   Dim DoubleValue As DoubleConsole.WriteLine _      ("DoubleValue's type is: " + _          DoubleValue.GetType().ToString())   ' Shows that DoubleValue's type is   ' System.Double

Thus when you test this assumption you can see that casting an Integer value type to a Double value type (or any other cast to one of the value types?DateTime, Boolean, Double, etc.), does indeed result in a change not only to the value being stored, but to the actual type of the structure holding that value.

   Dim IntegerValue as IntegerIntegerValue = _      CInt(DoubleValue)Console.WriteLine _      ("IntegerValue's type is: " + _       IntegerValue.GetType().ToString())   ' Shows that IntegerValue's type is   ' System.Int32

Casting Objects
While casting value types, such as Integers, Double, Long, Boolean, Date, etc., is pretty straightforward, the very meaning of casting when applied to reference types such as Objects Strings, Arrays, Interfaces, etc., is less clear, as is the actual behavior of reference types and how you use these behaviors to your advantage in writing applications.

The very meaning of casting when applied to reference types?objects, strings, arrays, interfaces?is less clear, as is the actual behavior and how you would use these behaviors to your advantage in writing applications.

Consider (again) the simple class hierarchy diagram in Figure 1. If you create an Array, you can cast that Array as an Object.

   Dim array1 As string = _       {"Alpha", "Bravo", "Charlie", "Delta", _     "Echo", "Foxtrot"}     Dim o1 As Object     ' Do an implicit cast...     o1 = array1     ' Or do an explicit cast...     o1 = CType(array1, Object)
Figure 2: IntelliSense showing the members of an array cast as an Object.

As you can see in this code sample, you can execute either an explicit or implicit cast with Option Strict on?the reason is that you’re “down” casting, i.e., casting from a specific to a general type. System.Array is derived from System.Object, so an implicit cast from Array to Object is allowed. Note the use of the new CType() function, which you can use to cast dissimilar types by specifying two arguments: the type to be cast, and the target type of that cast. (See Sidebar: Boxing)

Based on previous experiments with value types, you might expect that casting reference types also results in a change to the underlying type used to hold the values. In the following example, calling o1.GetType() returns a type of “Object.” However, this code also shows that even though you have cast array1 as an Object, the target, o1 still has a data type of “System.String[]”, which indicates an Array type containing string values.

   Console.WriteLine("The type of o1 is: " + _        o1.GetType().ToString())   ' Displays System.String[]

If you try to write code to examine the elements of the array, cast as object o1, IntelliSense shows you (Figure 2) that there are no elements to examine. The only exposed member that a token cast as System.Object has is the GetType() method, so it is impossible to interact with it as an array.

So what would be the result if you re-cast the o1 type as an Array?

   Dim array2 As Arrayarray2 = _      CType(o1, Array)Console.WriteLine _      ("Type of re-cast array is " _      + array2.GetType.ToString())   Console.WriteLine( _     "Re-casting o1 as array...Contents are:")   For Each s In array2      Console.WriteLine(s)   Next

The “object” o1 is re-cast as an Array. GetType() again shows that the type is System.String[], an array of string elements. Note that in this case, you must use the CType() function to make an explicit cast, as this is the type of implicit cast that is prohibited by Option Strict. Also, notice that the original array elements? “Alpha,” “Bravo,” etc., are magically “restored.” What’s going on here?

What happens is that when you cast an array as an Object, all of the members of the original type survive the cast?they simply are no longer accessible. In terms of its interface, the new object looks like the cast?in this case, an Object. Casting an array as an Object has the effect of cloaking the members that belong only to the array.

A moment’s reflection on the different behavior between making copies of value types versus reference types makes this obvious. If you create an Integer type and a Double type, and copy the value stored in the Integer type to the Double type, you can then change the value of the Integer type without affecting the new copy that resides in the Double type:

   Dim a As Integer   Dim b As Double   a = 10   b = a   a = 20   Console.WriteLine("The value of a is {0} " + _        "and the value of b is {1}",a,b)

The preceding code will print the following to the console:

   "The value of a is 20 and the value of b is 10"
When you make a copy of a reference type by casting, you still have a pointer to the original object.

However, when you copy a reference type, you get not a true copy but a new token that points to the same object. Special steps are needed to actually clone a reference type. As a result, it shouldn’t be too surprising that when you make a copy of a reference type by casting, you still have a pointer to the original object.

How does casting affect a non-intrinsic class, a custom class of your own creation?

The code in Listing 1 creates two classes. The first is a generic “Watercraft” class with a public Propel() method. This class is then subclassed and specialized as a “Canoe” class. The Canoe class adds a Paddling() method and overrides the Propel() method to call the Paddling() method. The Propel() method of the Watercraft class writes the phrase “Watercraft is moving…” to the console, and the Paddling() method of the Canoe class writes “Canoe is paddling…” to the console.

You can then instantiate the Canoe class and call the Paddling() method, which is to be expected. What would happen, however, if you cast the Canoe object as a Watercraft? Can you still call the Paddling() method?

The answer is no. The new object behaves as if the Paddling() method doesn’t exist, yet the GetType() method confirms that what you have is still a Canoe. Based on this understanding, what should you expect from calling the Propel() method? The answer depends on exactly how the members of the Canoe class have been cloaked to make it appear to be a Watercraft. If the entire derived class has been peeled away then a call to Propel() would result in a “Watercraft is moving…” string at the console. If, on the other hand, what is done is that the unique, Canoe-class-only members are hidden from the new object created by the casting, you’ll get the “Canoe is paddling…” string.

What’s happening? The Paddling() method may not be visible, but the overridden Propel() method is executed and it successfully calls the “hidden” Paddling() method! Casting, then, allows you to get an object reference that exposes a subset of the class’s members. Can you cast one object type to that of an unrelated class? As one might expect intuitively, the answer is “No.” For instance, if you create another class hierarchy consisting of a Bicycle class and a derived MountainBike class, you could try the following:

   Dim canoe1 As Canoe = New Canoe()   Dim bike1 As MountainBikebike1 = _      CType(canoe1, MountainBike)

However, you’re immediately presented with a compiler error indicating that it is impossible to convert a canoe into a mountain bike (no surprise). Can you get clever and still fool the compiler? You can but it doesn’t do much good as the following code demonstrates:

   Dim bike1 As Object   bike1 = CType(canoe1, Object)   Dim bike2 As MountainBike   bike2 = CType(bike1, MountainBike)

This code compiles but generates an “Invalid cast exception error”.

If you review the class diagram in Figure 1, you can see what the governing principle is. You can cast an object as any one of its ancestors, and once cast, you can re-cast the resulting reference back to any class in the hierarchy chain including the original class used to define the original object. Of much more significance to note is that System.Object is the parent class, and as such, you can cast any object as an Object, the lowest common denominator (or lowest common ancestor) of all classes in the .NET Framework!

Casting and Interfaces
You may wonder what use all of this is to you as a developer. The ability to reduce the members of a class to a subset?a subset that it may share with other, different classes?allows you to work with a collection of such objects. As you know, to create the simplest of collections, an array, you must define the type of elements the array will be able to store. You may wish to store a group of different objects to an array, which would be impossible if you could not cast the objects into a common type.

For example, assume you have an Employee class with subclasses such as SalesPerson, Supervisor, CustomerServiceRep, and so on. You may wish to create an array-based collection of a group of these objects with access to a common Employee class member such as a CurrentPayRate() property. However, in their “native” state, this would not be possible. You cannot do the following:

   Dim Employees() As SalesPerson Or Supervisor_   Or CustomerServiceRep

However, you can do this:

   Dim Employees(2) As Employee   Employees(0) = CType(New _      SalesPerson(),"Employee")   Employees(1) = CType(New _   Supervisor(),"Employee")   Employees(2) = CType(New _   CustomerServiceRep(),"Employee")   Dim i As Integer   For i = 0 to UBound(Employees)        Console.WriteLine("Current rate of pay is "_         + Employees(i).CurrentPayRate.ToString()   End For

This works fine for a group of objects that may be based on the same superclass, or otherwise share a common ancestor. However, there may be disparate classes that you need to process as a collection, or pass as an argument to a method that do not share any common ancestor other than System.Object. How can you use casting to work around this? You can indeed cast such objects as a System.Object then recast them to their native types, but this may require more knowledge about the objects than you may possess in a given situation. Interfaces, however, are tailor-made to address this issue.

Any group of object classes can implement a common interface, and such an interface can be used in an object collection or passed as an argument by extracting the interface alone, using the CType() function to cast the object as it’s interface.

You may have noticed in the Watercraft class that it implements the ITopSpeed interface. The code for this interface is as follows:

   Interface ITopSpeed        Property TopSpeed() As Integer   End Interface

Each class that implements this interface has specific code to return a value from or store a value to a private field. Because the Watercraft class implements this interface, any derived class will inherit this interface. The Bicycle class and its derived class also implement the ITopSpeed interface, thus you can create an array to hold references to this interface and work with any members defined by this interface without regard to the fact that the interfaces may belong to vastly different classes. The code in Listing 2 shows how (in a very simple manner) this can be used:

Figure 3 shows the output from executing this code.

Figure 3: Using an interface reference to work with a collection of disparate objects.

It has always been important for programming languages to provide the ability to convert values from one type to another. .NET languages let you convert object references based on one class to another object reference that appears and behaves like an object based on another class.

If you understand and use casting, it is possible to usefully aggregate class instances.

If you understand and use casting it is possible to usefully aggregate class instances whether you want to access them as a collection or create generic black-box methods and functions that can accept any class instance cast as an object or an implemented interface. This could then re-cast the class instances back into their original type to access type members, or in the case of an interface, access the interface members directly.

For example, many intrinsic interfaces in the .NET Framework, such as IComparable.CompareTo() specify an argument of type Object, but to implement the interface method on a specific class, you can recast the object to the appropriate class to process class-specific members. You may think that the behavior of casting when applied to reference types may seem awkward or counter-intuitive, but once you understand them they make perfect sense and their utility starts to become apparent.

devx-admin

devx-admin

Share the Post:
Performance Camera

iPhone 15: Performance, Camera, Battery

Apple’s highly anticipated iPhone 15 has finally hit the market, sending ripples of excitement across the tech industry. For those considering upgrading to this new

Battery Breakthrough

Electric Vehicle Battery Breakthrough

The prices of lithium-ion batteries have seen a considerable reduction, with the cost per kilowatt-hour dipping under $100 for the first occasion in two years,

Economy Act Soars

Virginia’s Clean Economy Act Soars Ahead

Virginia has made significant strides towards achieving its short-term carbon-free objectives as outlined in the Clean Economy Act of 2020. Currently, about 44,000 megawatts (MW)

Renewable Storage Innovation

Innovative Energy Storage Solutions

The Department of Energy recently revealed a significant investment of $325 million in advanced battery technologies to store excess renewable energy produced by solar and

Chip Overcoming

iPhone 15 Pro Max: Overcoming Chip Setbacks

Apple recently faced a significant challenge in the development of a key component for its latest iPhone series, the iPhone 15 Pro Max, which was unveiled just a week ago.

Performance Camera

iPhone 15: Performance, Camera, Battery

Apple’s highly anticipated iPhone 15 has finally hit the market, sending ripples of excitement across the tech industry. For those considering upgrading to this new model, three essential features come

Battery Breakthrough

Electric Vehicle Battery Breakthrough

The prices of lithium-ion batteries have seen a considerable reduction, with the cost per kilowatt-hour dipping under $100 for the first occasion in two years, as reported by energy analytics

Economy Act Soars

Virginia’s Clean Economy Act Soars Ahead

Virginia has made significant strides towards achieving its short-term carbon-free objectives as outlined in the Clean Economy Act of 2020. Currently, about 44,000 megawatts (MW) of wind, solar, and energy

Renewable Storage Innovation

Innovative Energy Storage Solutions

The Department of Energy recently revealed a significant investment of $325 million in advanced battery technologies to store excess renewable energy produced by solar and wind sources. This funding will

Renesas Tech Revolution

Revolutionizing India’s Tech Sector with Renesas

Tushar Sharma, a semiconductor engineer at Renesas Electronics, met with Indian Prime Minister Narendra Modi to discuss the company’s support for India’s “Make in India” initiative. This initiative focuses on

Development Project

Thrilling East Windsor Mixed-Use Development

Real estate developer James Cormier, in collaboration with a partnership, has purchased 137 acres of land in Connecticut for $1.15 million with the intention of constructing residential and commercial buildings.

USA Companies

Top Software Development Companies in USA

Navigating the tech landscape to find the right partner is crucial yet challenging. This article offers a comparative glimpse into the top software development companies in the USA. Through a

Software Development

Top Software Development Companies

Looking for the best in software development? Our list of Top Software Development Companies is your gateway to finding the right tech partner. Dive in and explore the leaders in

India Web Development

Top Web Development Companies in India

In the digital race, the right web development partner is your winning edge. Dive into our curated list of top web development companies in India, and kickstart your journey to

USA Web Development

Top Web Development Companies in USA

Looking for the best web development companies in the USA? We’ve got you covered! Check out our top 10 picks to find the right partner for your online project. Your

Clean Energy Adoption

Inside Michigan’s Clean Energy Revolution

Democratic state legislators in Michigan continue to discuss and debate clean energy legislation in the hopes of establishing a comprehensive clean energy strategy for the state. A Senate committee meeting

Chips Act Revolution

European Chips Act: What is it?

In response to the intensifying worldwide technology competition, Europe has unveiled the long-awaited European Chips Act. This daring legislative proposal aims to fortify Europe’s semiconductor supply chain and enhance its

Revolutionized Low-Code

You Should Use Low-Code Platforms for Apps

As the demand for rapid software development increases, low-code platforms have emerged as a popular choice among developers for their ability to build applications with minimal coding. These platforms not

Cybersecurity Strategy

Five Powerful Strategies to Bolster Your Cybersecurity

In today’s increasingly digital landscape, businesses of all sizes must prioritize cyber security measures to defend against potential dangers. Cyber security professionals suggest five simple technological strategies to help companies

Global Layoffs

Tech Layoffs Are Getting Worse Globally

Since the start of 2023, the global technology sector has experienced a significant rise in layoffs, with over 236,000 workers being let go by 1,019 tech firms, as per data

Huawei Electric Dazzle

Huawei Dazzles with Electric Vehicles and Wireless Earbuds

During a prominent unveiling event, Huawei, the Chinese telecommunications powerhouse, kept quiet about its enigmatic new 5G phone and alleged cutting-edge chip development. Instead, Huawei astounded the audience by presenting

Cybersecurity Banking Revolution

Digital Banking Needs Cybersecurity

The banking, financial, and insurance (BFSI) sectors are pioneers in digital transformation, using web applications and application programming interfaces (APIs) to provide seamless services to customers around the world. Rising

FinTech Leadership

Terry Clune’s Fintech Empire

Over the past 30 years, Terry Clune has built a remarkable business empire, with CluneTech at the helm. The CEO and Founder has successfully created eight fintech firms, attracting renowned

The Role Of AI Within A Web Design Agency?

In the digital age, the role of Artificial Intelligence (AI) in web design is rapidly evolving, transitioning from a futuristic concept to practical tools used in design, coding, content writing

Generative AI Revolution

Is Generative AI the Next Internet?

The increasing demand for Generative AI models has led to a surge in its adoption across diverse sectors, with healthcare, automotive, and financial services being among the top beneficiaries. These

Microsoft Laptop

The New Surface Laptop Studio 2 Is Nuts

The Surface Laptop Studio 2 is a dynamic and robust all-in-one laptop designed for creators and professionals alike. It features a 14.4″ touchscreen and a cutting-edge design that is over

5G Innovations

GPU-Accelerated 5G in Japan

NTT DOCOMO, a global telecommunications giant, is set to break new ground in the industry as it prepares to launch a GPU-accelerated 5G network in Japan. This innovative approach will

AI Ethics

AI Journalism: Balancing Integrity and Innovation

An op-ed, produced using Microsoft’s Bing Chat AI software, recently appeared in the St. Louis Post-Dispatch, discussing the potential concerns surrounding the employment of artificial intelligence (AI) in journalism. These