User-Defined Value Types 

A value type is similar to a class except that instead of being a reference to an object on the heap, a value type is an aggregate that can be created directly on the stack, just like a primitive type. But, like classes, value types can have constructors, constants, fields, methods, properties, and nested types as members. However, the following restrictions apply when defining a value type:

  • Value types must extend ValueType.

  • Value types must explicitly be declared final.

  • Value types cannot be declared abstract.

  • Members of the class can be declared public and private, but not protected. If unspecified, access is package scoped.

  • A parameterless constructor cannot be declared in value types.

  • Field initializers are not allowed on instance fields in value types. However, static fields can have field initializers.

  • It is an error for the constructor of a user-defined value type to call super.

  • Value types cannot declare a finalize method.

  • Value types do not support Java reflection and cannot be serialized as Java types. Use .NET Framework reflection and .NET Framework serialization for these types

  • Value types are not available with the /x:net option.

You can instantiate value types in two ways. You can instantiate a value type in an uninitialized form or in an initialized form by using the new operator. Although the new operator is invoked, the value type object is allocated on the stack, not the heap. The lifetime of the object is the lifetime of the stack frame in which it is created. When the scope in which it is declared goes out of scope, the object is destroyed.

The following example shows the definition and instantiation of a simple value type.

Example

// value_type.jsl
public final class Point extends System.ValueType
{
    public int x;
    public int y;
}
class CMain
{
    public static void main()
    {
        Point p = new Point();
        p.x = 5;
        p.y = 10;
        System.Console.WriteLine("Point [x,y] = " + p.x + ", " + p.y);
    }
}

Output

Point [x,y] = 5, 10

A value type, if not assigned to or initialized with the new operator, is considered uninitialized.

A value type has a default value that is used in certain contexts, such as when an array of value types is created. The default value is the value produced by setting all value type fields to their default values and reference types to null. For example, primitive integer types have a default value of 0, so in the following code, members of Point x and y will be set to zero in all objects in the array:

Point[] pa = new Point[100];

Because each value type has an implicitly defined parameterless constructor that produces the default value as described, it is an error to declare a parameterless constructor in a value type.

Value types can reference the inherited members of ValueType.

User-defined value types have value semantics, not reference semantics. With reference types, it is possible to have two references to the same object. With value types, each instance contains its own copy of the data. When a value type is assigned, the data is copied. When a reference type is assigned, only the reference is copied. Thus, for reference types, it is possible for operations to affect an instance shared by two references. This is impossible for value types, which always operate on their own unique instance.

Similarly, when a value type is passed as an argument to a function, the function will create its own copy of the object, unless the function uses the Defining Methods That Take Arguments By Reference tag to specify that it takes the parameter by reference.

See Also

Reference

Using Value Types
Syntax for Targeting the .NET Framework
Property and Event Exposure