User Defined Casts

There are times when you may find yourself writing code to move data from a type you defined to another type either predefined or user defined. Of course we are all aware of polymorphism between derived types. This isn't always possible or practical depending on your intentions. It is particularly hard when you're converting between a primiritive type and a user defined type. The answer to this dilemma is to define your own cast.

Review
As you know, casting is the process of converting one datatype to another. Implicit conversions are automatic and can occur when no data will be lost. Data can be lost when the amount of memory space reserved for the target datatype is less than the memory space used used by the source datatype. Just like trying to pour 2 cups of water into a 1 cup container, data can be lost like the water that spills over. The answer to this dilemma is the explicit conversion where you explicitly acknowledge that the data will be lost and allow it to be lost.  These types of casts are available for predefined datatypes. Normally the predefined casts and polymorphism will suffice, but for those times when you find yourself moving data manually between types, user defined casts are the answer.

Syntax
Type conversions for your own datatypes are possible but you must define them yourself. You do this by defining your cast within one of the classes from which you will cast. You will also need to mark your cast operation as either implicit or explicitr. A good rule of thumb is to define your cast as explicit if therre is any risk of an exception or if any of the data in the source type might fail to be transferred to the target type. Casting operators can be written into structs and classes. The syntax is similar to overloading an operator as shown below:

// The person class is an abstract class defining basic person information.
public
abstract class Person
{
public string firstName;
public string lastName;
public Person(string first, string last)
{
this.firstName = first;
this.lastName = last;
}
public Person()
{}
}

// The Farrier class inherits from the Person class.
public
class Farrier : Person
{
public string expertise;
public Farrier(string first, string last, string expertise):base(first,last)
{
this.expertise = expertise;
}

// Note the explicit conversion operator.
//
This does not technically need to be explicit as no data will be lost and no exceptions will occur.
public static explicit operator Veterinarian(Farrier value)
{
string
fName = value.firstName;
string
lName = value.lastName;
string
specialty = value.expertise;
return new Veterinarian
(fName, lName, specialty);
}

}

 // This is the Veterinarian class that in herits from the Person class.
public
class Veterinarian : Person
{
public string specialty;
public Veterinarian(string first, string last, string specialty):base(first,last)
{
this.specialty = specialty;
}

// Note the implicity conversion operator.
public static implicit operator Farrier(Veterinarian value)
{

string
fName = value.firstName;
string
lName = value.lastName;
string
expertise = value.specialty;
return new Farrier
(fName, lName, expertise);
}

}

// The Form code.
public
partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}

// Using the implicit conversion
private void farrierToVet_Click(object sender, EventArgs e)
{
Farrier a = new Farrier
(farrierFName.Text, farrierLName.Text, farrierExpertise.Text);
Veterinarian b = (Veterinarian
)a;
veterinarianFName.Text = b.firstName;
veterinarianLName.Text = b.lastName;
veterinarianSpecialty.Text = b.specialty;
}

// Using the explicit conversion.
private void vetTofarrier_Click(object sender, EventArgs
e)
{
Veterinarian b = new Veterinarian
(veterinarianFName.Text, veterinarianLName.Text, veterinarianSpecialty.Text);
Farrier
a = b;
farrierFName.Text = a.firstName;
farrierLName.Text = a.lastName;
farrierExpertise.Text = a.expertise;
}

// Attempting to use polymorphism.
private void polymorphicFarriertoVet_Click(object sender, EventArgs
e)
{
Farrier a = new Farrier
(farrierFName.Text, farrierLName.Text, farrierExpertise.Text);
Person
c = a;
// The following causes compile error:
//Cannot implicitly convert type 'UserDefinedCasts.Person' to 'UserDefinedCasts.Veterinarian'.
//An explicit conversion exists (are you missing a cast?) C:\Documents and Settings\Desirea\My Documents\Visual Studio 2008\Projects\UserDefinedCasts\UserDefinedCasts\Form1.cs 43 30 UserDefinedCasts
//
// Veterinarian b = c;
MessageBox.Show("Conversions would not work even with explicit conversion. Person does not contain a casting operator."
,
"Polymorphic Conversion Not Possible"
,
MessageBoxButtons
.OK,
MessageBoxIcon
.Error);
}
}

Usage
User defined casts are a good way to reduce code. If you find yourself writing code to move data from one of your datatypes to another, defining your own casts within one of the classes or structs will make the job a lot simpler. It's also a good solution when inheritance won't resolve the issue via polymorphism. You can also decouple classes that while containing similar data do not necessarily need to be tied together as in the case of integers and floats. I'm sure someone has some more suggestions as to how to use user defined casts. Feel free to post them below.

Print | posted on Sunday, July 05, 2009 11:17 AM

Feedback

No comments posted yet.

Your comment:





 
Please add 4 and 3 and type the answer here:

Copyright © Desirea Herrera

Design by Bartosz Brzezinski

Design by Phil Haack Based On A Design By Bartosz Brzezinski