< Class, Object & Managed Code 8 | Main | C++ .NET Value Type 2 >


 

 

Value Types 1

 

 

What we have in this page?

 

  1. Reference Types and Value Types

  2. The Need for Value Types

  3. Properties of Value Types

  4. Structures

  5. Creating and Using a Simple Struct

-----------Next-------------------------

  1. Debugging the Structure

  2. Differences Between Structures and Classes

  3. Implementing Constructors for a Struct

  4. Using One Struct Inside Another

  5. Copying Structs

  6. Enumerations

  7. Creating and Using an Enum

  8. Using Enums in Programs

  9. Avoiding Ambiguity

  10. Using Memory Efficiently

  11. Quick Reference

 

Many data types within .NET are represented by classes that are referred as a reference type. However, not every data type in .NET is a class, and now you’re going to meet the other fundamental building block of .NET types, the value type. In this module, you’ll discover what value types are and how they differ from the reference types you’ve already learned. You will also meet two important value types, structures and enumerations.

 

Reference Types and Value Types

 

Classes are known as reference types because you always access objects by using reference variables. Consider the following traditional C++ and C++ .Net code snippets respectively:

class MyClass

{

      // ...

};

 

int main(array<System::String ^> ^args)

{

      MyClass* pc = new MyClass();

      // ...

      result = pc->DoOperation();

      return 0;

}

 

ref class MyClass

{

      // ...

};

 

int main(array<System::String ^> ^args)

{

      MyClass^ pc = gcnew MyClass();

 

      result = pc->DoOperation();

      // ...

      return 0;

}

Then let take out the following objects instantiation.

MyClass* pc = new MyClass();

MyClass^ pc = gcnew MyClass();

In this example, for C++ .Net, pc is a reference variable that lets us refer to the MyClass object created by the gcnew operator. Accessing objects using references in this way allows the .NET garbage-collection mechanism to reclaim the resources used by an object when nobody has a reference to it any more. This feature of .NET makes for efficient memory usage and means that you won’t suffer from one of the traditional problems of C++ programs, memory leaks. The second thing you’ve learned about classes is that they consist of data members and member functions. Data members represent the state of the object, and it’s good practice to make them private to the class. Member functions provide the behavior of the object, what the object can or will do and they use the data members to determine how to respond. All operations on objects are done by calling member functions, using the ─> operator, as in the following line of code:

result = pc->DoOperation();

The Need for Value Types

 

As the name value type implies, they have been designed to hold values, such as integers, floating-point numbers, booleans, and characters. Anything that is basically a wrapper around a simple value and is less than about 16 bytes in size, is a good candidate for a value type. We need value types because we want simple values to be used as efficiently as possible, but we also want them to be usable as objects. Using values as objects is a problem with object-oriented languages (such as traditional C++) because if basic types are represented as objects, all operations (such as addition and multiplication of integers) have to be done by calling functions, which isn’t efficient at all. On the other hand, if basic types are not represented as objects, operations on them can be very efficient but we can’t use them where objects are needed.

.NET gets around this problem with value types, which are represented and used as efficiently as built-in types, but which can also be used as objects when necessary. You don’t need to know this is happening most of the time. This process called boxing and will be discussed later. Well, now we already have reference, value and built-in types. The following table summarizes the value types provided by the .NET Framework. The program examples that demonstrate the usage of these types have been included in Type, Variable and Operators module.

 

Value Type

Description

Managed C++ Equivalent Type

Byte

An 8-bit unsigned integer

char

SByte

An 8-bit signed integer

signed char

Int16

A 16-bit signed integer

short

Int32

A 32-bit signed integer

int or long

Int64

A 64-bit signed integer

__int64

UInt16

A 16-bit unsigned integer

unsigned short

UInt32

A 32-bit unsigned integer

unsigned int or unsigned long

UInt64

A 64-bit unsigned integer

unsigned __int64

Single

A single-precision, 32-bit, floating-point number

float

Double

A double-precision, 64-bit, floating-point number

double

Boolean

A Boolean value

bool

Char

A 16-bit Unicode character

wchar_t

Decimal

A 96-bit decimal value

decimal

IntPtr

A signed integer whose size depends on the platform

No built-in type

UIntPtr

An unsigned integer whose size depends on the platform

No built-in type

 

Table 1

 

Note that the C++ equivalents are simply names for the types, aliases, if you like, those are rather more C++ like in nature. Although it’s more natural to use the native language equivalents, you could use the underlying .NET types instead, which means that the following two lines of code mean exactly the same thing, for example:

int n = 0;              // use managed C++ type

System::Int32 n = 0;    // use .NET native type

Properties of Value Types

 

A value type is a type that inherits from the System::ValueType class. Value types have several special properties:

  1. Value types are stored on the stack (unlike references, which are stored on the run-time heap).

  2. Instances of value types are always accessed directly (unlike reference types, which are accessed through references). Direct access means that you don’t use the new operator when creating instances.

  3. Copying value types copies the value, rather than the reference.

As you can see, value types behave just like the standard built-in types, such as int and char, and they are just as efficient to use. As mentioned before, the main difference between value types and built-in types is that value types can also be treated as objects when necessary.

 

 

 

 

Structures

 

Structures (struct) provide a way to create the compound data or record types that you might have come across in other programming languages. Like classes, structures can contain member functions, data members, properties, delegates, and events, but there’s one important difference: structures are value types, not reference types. Therefore, if you have a value type that needs to have some internal structure, such as a point with X and Y coordinates, you can implement it using a struct. The following exercise shows how to create a structure representing a point, how to create instances of the structure, and how to use the instances in code. Both traditional and managed C++ use the struct keyword to define structures. This module discusses the use of .NET (managed) structs rather than the traditional struct. Declaring .NET structures has the advantage of working within the .NET world and also allows you to exchange structures with other .NET languages.

 

Creating and Using a Simple Struct

 

1.        Start Microsoft Visual Studio .NET, and create a new CLR Console Application (.NET) project named Structs.

 

Creating the new C++ .NET project - CLR Console Application

 

2.        At the top of the Structs.cpp file, immediately under using namespace System;, add the following structure definition:

// The Point structure definition

// The version 1 of the Managed Extensions for C++

// uses __value

value struct Point

{

   public:

         int x, y;

};

Adding a structure definition to the main project file

 

The value and struct keywords start a structure definition, and you’ll notice that structures look very similar to classes in the way they are defined. The body of the structure is enclosed in braces and finishes with a semicolon, and the public and private keywords are used to set the access level for structure members. Notice the use of the value keyword here. This keyword tells the compiler that this is a value type and not a traditional C++ structure. It’s important that you remember to use value when defining your structures. This simple structure represents a point on a graph, so it has two integer data members representing the X and Y coordinates.

 

3.        To create and initialize a Point object, add the following lines to the main() function of your application. Delete the provided Hello World code.

 

      // Create a Point

      Point p1;

      // Initialize its members

      p1.x = 10;

      p1.y = 20;

 

Notice that the code doesn’t use the new or gcnew operator. Those operators are used to create references to objects, and value types aren’t accessed by reference. Instead, a Point has been created on the program stack, and you access it directly as p1. Because the data members are public at this point, you can access them using the usual dot notation.

 

4.        Add two lines to print out the value of one of the struct members, like this:

 

      // Write to the standard output

      Console::Write("p1.x is ");

      Console::WriteLine(p1.x);

 

Create, initialize and use the structure

 

5.        If you compile and run the program at this point, you should see the output p1.x is 10 as shown below.

 

Structure, a value type program example console output

 

 

 

 

 

Part 1 | Part 2 | Part 3 | Part 4

 

 


< Class, Object & Managed Code 8 | Main | C++ .NET Value Type 2 >