Most programming languages provide built-in data types, like integers and floating point numbers, that are copied when they are passed as arguments. This differs from the way objects are treated: they are always passed by reference. The NGWS runtime generalizes the idea of built-in data types to allow for user-defined data types that are passed by value. These types are called value types.
Value types are stored as efficiently as primitive types, yet you can call methods on them, including the virtual methods defined on the System.Object class as well as any non-static methods defined on the value type itself. The NGWS Frameworks define built-in value types such System.Int32 and System.Boolean, which correspond to primitive data types used by language compilers; you can use them interchangeably with your language compiler's primitive types. Value types can be instantiated, passed as parameters, stored as local variables, or stored in a field of another value type or object.
You can define your own value types by deriving a type from System.ValueType or by using special syntax that your language compiler requires. Value types do not have the overhead associated with storing an instance of a class. If you want to define a type representing a value that is small, such as a complex number (using two floating point numbers), you might choose to define it as a value type because you can pass the value type efficiently by value. If the type you are defining would be more efficiently passed by reference, you should define it as a class instead.
For each value type, the runtime supplies a corresponding boxed type, which has the base type specified in the class definition. Some language compilers require you to use special syntax when the boxed type is required; others automatically use the boxed type when it is needed. When you define a value type, you are defining both the unboxed type and the boxed type that is associated with the value type.
Value types can have fields, properties, and events. They can also have static and non-static methods. When they are boxed, they inherit the virtual methods from System.ValueType, and they can implement zero or more interfaces. Constructors are not required on value types.
Value types are sealed, meaning that no other type can be derived from them. However, you can define virtual methods directly on the value type, and these can be called on either the boxed or unboxed form of the value type. Even though you cannot derive another type from a value type, you might define virtual methods on a value type when you are using a language in which it is more convenient to work with virtual methods than non-virtual or static methods.
Value types do not require a constructor to be called when an instance is created. The contents of a value type are guaranteed to be initially zero (null for object fields).