1.8 Creating Value Types with struct

 <  Day Day Up  >  

1.8 Creating Value Types with struct

You want to create a new data type that behaves more like a value than a class.


Technique

Define a structure using the struct keyword. A struct behaves similar to a class in that it can contain any number of member variables , methods , properties, and indexers, but memory for it is allocated on the stack rather than the heap, which also implies that it is passed by value rather than by reference. The following code demonstrates a temperature value type that performs a conversion if the Fahrenheit property is accessed:

 
 struct TemperatureStruct {     public double Celsius;     public double Fahrenheit     {         get         {             return ((9d/5d)*Celsius)+32;         }         set         {             Celsius = (5d/9d)*(value-32);         }     } } 

Comments

Sometimes, a language's built-in data types just aren't sufficient to use as a data-storing mechanism. Although using them would most certainly work, you generally need several related variables to describe all the pieces of pertinent information about a single object or abstract value type. Structures, or structs , were designed to organize and group built-in data types to create user -defined types that could emulate values.

One of the most prominent distinguishing differences between structs and classes is that you do not have to instantiate a struct using the new operator. You don't have to declare a default constructor because the compiler will ensure that all members are initialized by using a process known as static flow analysis . Sometimes, however, the analysis is unable to determine whether a member can be initialized. You can make the determination by declaring a private member variable within your struct. In this case, you have to create a custom parameterized constructor, and clients using your struct must create it using the new operator. Based on this information, you might make the assumption that using new on the struct would then allocate it on the heap. We can in fact verify that it does not by looking at the intermediate language (IL) code generated by the compiler using a tool, ILDasm, which is perfect when you want to investigate a certain behavior.

To run the ILDasm tool, you need to navigate to the bin directory of the .NET Framework SDK. You can double-click on the file to run it, but there are some advanced options available if you run the executable and specify the command-line argument /ADV . For this exercise, you can simply run it without the advanced options. Listing 1.4 shows an application that contains a class called TemperatureClass and a struct named TemperatureStruct . When you build this application, open the assembly in ILDasm. Expand the tree item of the namespace that contains the class and struct definition, which in this case is _8_ValueTypes . You should see three data types defined in the assembly: the main entry point, the temperature class, and the temperature struct. Expand the tree item that denotes the class where the entry point is located. Finally, double-click on the Main function to display the disassembled IL code shown in Figure 1.2.

Listing 1.4 Comparing Differences Between a Class and a Struct
 using System; namespace _8_ValueTypes {     class EntryPoint     {         [STAThread]         static void Main(string[] args)         {             TemperatureStruct ts = new TemperatureStruct();             TemperatureClass tc = new TemperatureClass();             Console.Write( "Enter degrees in Celsius: " );             string celsius = Console.ReadLine();             ts.Celsius = Convert.ToDouble(celsius);             Console.WriteLine( "Temperature in Fahrenheit = {0}", ts.Fahrenheit );         }     }     class TemperatureClass     {         private double degreesCelsius;         public double Fahrenheit         {             get             {                 return ((9d/5d)*degreesCelsius)+32;             }             set             {                 degreesCelsius = (5d/9d)*(value-32);             }         }         public double Celsius         {             get             {                 return degreesCelsius;             }             set             {                 degreesCelsius = value;             }         }     }     struct TemperatureStruct     {         public double Celsius;         public double Fahrenheit         {             get             {                 return ((9d/5d)*Celsius)+32;             }             set             {                 Celsius = (5d/9d)*(value-32);             }         }     } } 
Figure 1.2. ILDasm is a good tool to understand the inner workings of your application and how it interacts with the CLR.

graphics/01fig02.gif

One particular portion of the IL for the Main function in Listing 1.4 is the four lines following the declaration of the locals that are used within the function:

 
 IL_0000:  ldloca.s   ts IL_0002:  initobj    _8_ValueTypes.TemperatureStruct IL_0008:  newobj     instance void_8_ValueTypes.TemperatureClass::.ctor() IL_000d:  stloc.1 

The first two lines initialize the struct. The important piece of information here is the instructions ldloca and initobj . Compare these two instructions with the two that are used for initialization of the temperature class, newobj and stloc . When you use the new operator on the class, it generates the newobj instruction using the class constructor as the operand. However, when you use new on the struct, it performs a ldloca.s , which is an instruction used to fetch an object from the stack. Based on this information, even though you use the new keyword on a struct, it still follows the rules in that it is a stack-allocated rather than a heap-allocated object.

Note

Most of the built-in C# data types are structs themselves . For instance, the int is simply an alias for the System.Int32 structure.


 <  Day Day Up  >  


Microsoft Visual C# .Net 2003
Microsoft Visual C *. NET 2003 development skills Daquan
ISBN: 7508427505
EAN: 2147483647
Year: 2003
Pages: 440

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net