User-Defined Conversions Tutorial
This tutorial shows how to define and use conversions to or from classes or structs.
Sample Files
See User-Defined Conversions Sample to download and build the sample files discussed in this tutorial.
Further Reading
- explicit
- implicit
- () Operator
- Implicit Numeric Conversions Table
- operator
- 6.4 User-defined conversions
- 6.4.4 User-defined explicit conversions
Tutorial
C# allows programmers to declare conversions on classes or structs so that classes or structs can be converted to and/or from other classes or structs, or basic types. Conversions are defined like operators and are named for the type to which they convert.
In C#, conversions can be declared either as implicit, which occur automatically when required, or explicit, which require a cast to be called. All conversions must be static, and must either take the type the conversion is defined on, or return that type.
This tutorial introduces two examples. The first example shows how to declare and use conversions, and the second example demonstrates conversions between structs.
Example 1
In this example, a RomanNumeral type is declared, and several conversions to and from it are defined.
// conversion.cs
using System;
struct RomanNumeral
{
public RomanNumeral(int value)
{
this.value = value;
}
// Declare a conversion from an int to a RomanNumeral. Note the
// the use of the operator keyword. This is a conversion
// operator named RomanNumeral:
static public implicit operator RomanNumeral(int value)
{
// Note that because RomanNumeral is declared as a struct,
// calling new on the struct merely calls the constructor
// rather than allocating an object on the heap:
return new RomanNumeral(value);
}
// Declare an explicit conversion from a RomanNumeral to an int:
static public explicit operator int(RomanNumeral roman)
{
return roman.value;
}
// Declare an implicit conversion from a RomanNumeral to
// a string:
static public implicit operator string(RomanNumeral roman)
{
return("Conversion not yet implemented");
}
private int value;
}
class Test
{
static public void Main()
{
RomanNumeral numeral;
numeral = 10;
// Call the explicit conversion from numeral to int. Because it is
// an explicit conversion, a cast must be used:
Console.WriteLine((int)numeral);
// Call the implicit conversion to string. Because there is no
// cast, the implicit conversion to string is the only
// conversion that is considered:
Console.WriteLine(numeral);
// Call the explicit conversion from numeral to int and
// then the explicit conversion from int to short:
short s = (short)numeral;
Console.WriteLine(s);
}
}
Output
10 Conversion not yet implemented 10
Example 2
This example defines two structs, RomanNumeral and BinaryNumeral, and demonstrates conversions between them.
// structconversion.cs
using System;
struct RomanNumeral
{
public RomanNumeral(int value)
{
this.value = value;
}
static public implicit operator RomanNumeral(int value)
{
return new RomanNumeral(value);
}
static public implicit operator RomanNumeral(BinaryNumeral binary)
{
return new RomanNumeral((int)binary);
}
static public explicit operator int(RomanNumeral roman)
{
return roman.value;
}
static public implicit operator string(RomanNumeral roman)
{
return("Conversion not yet implemented");
}
private int value;
}
struct BinaryNumeral
{
public BinaryNumeral(int value)
{
this.value = value;
}
static public implicit operator BinaryNumeral(int value)
{
return new BinaryNumeral(value);
}
static public implicit operator string(BinaryNumeral binary)
{
return("Conversion not yet implemented");
}
static public explicit operator int(BinaryNumeral binary)
{
return(binary.value);
}
private int value;
}
class Test
{
static public void Main()
{
RomanNumeral roman;
roman = 10;
BinaryNumeral binary;
// Perform a conversion from a RomanNumeral to a
// BinaryNumeral:
binary = (BinaryNumeral)(int)roman;
// Performs a conversion from a BinaryNumeral to a RomanNumeral.
// No cast is required:
roman = binary;
Console.WriteLine((int)binary);
Console.WriteLine(binary);
}
}
Output
10 Conversion not yet implemented
Code Discussion
- In the preceding example, the statement:
binary = (BinaryNumeral)(int)roman;
performs a conversion from a
RomanNumeralto aBinaryNumeral. Because there is no direct conversion fromRomanNumeraltoBinaryNumeral, a cast is used to convert from aRomanNumeralto an int, and another cast to convert from an int to aBinaryNumeral. - Also the statement:
roman = binary;
performs a conversion from a
BinaryNumeralto aRomanNumeral. BecauseRomanNumeraldefines an implicit conversion fromBinaryNumeral, no cast is required.