Export (0) Print
Expand All

5 __value Classes

Visual Studio .NET 2003

__value classes are intended to hold small data items with short lifetimes. A __value class differs from a __gc class in that objects can exist on the runtime stack as well as the runtime heap. This avoids the overhead of garbage collection for every allocation or deallocation.

__value classes can be declared as local variables, parameters, and return values. They can also be embedded in __gc classes, and as static or C++ heap-allocated variables as described below.

The keyword __value introduces the declaration of a __value class.

Example

// __value_classes.cpp
// compile with: /clr
#using <mscorlib.dll>
using namespace System;

__value struct V { int i; };

__gc struct G {
   // embedded in __gc class
   V v;
};  

V f(V v) {     // pass by value on the runtime stack
   v.i += 1;   // does not affect value at call site
   return v;   // return by value
}

int main() {
   V v1 = {10};    // declare & initialize on runtime stack
   V v2 = f(v1);   // pass by value and return by value
   G *pG = new G;  // allocated as part of G instance
   pG->v = v1;     // copy value
   pG->v.i += v2.i;
   Console::WriteLine(v1.i);
   Console::WriteLine(v2.i);
   Console::WriteLine(pG->v.i);
}

Output

10
11
21

The default layout for value classes is System::Reflection::TypeAttributes::LayoutSequential.

As in C++, the difference between a __value struct and a __value class is that the default access and inheritance of a struct is public, and that of a class is private.

Characteristics

The following are supported for __value classes.

  • A declaration of a __value class shall always have the __value keyword.
  • A __value class can have a data member that has type pointer-to any unmanaged type.
  • A __value class can override any method of the managed class System::ValueType (Section 5.2.4).
  • A __value class can implement any number of __gc interfaces (Section 6) and it must implement all of their methods.
  • An object of a __value class that does not contain any __gc pointers (Section 7) can be allocated anywhere an unmanaged class can be allocated, for example, the C++ heap or global data.
  • A __value class can contain properties (Section 13).
  • A __value class can be marked as "sealed" (Section 18).
  • A __value class can declare a constructor.
  • A __value class can declare a static class constructor (Section 19).
  • A __value class can have a visibility specifier (Section 21.1).
  • A __value class can contain an embedded object of an unmanaged POD type. POD types are defined in Section 9, Paragraph 4 of the C++ ISO Standardiv. In particular, they contain no nonstatic data members, virtual functions, base classes, or user-defined constructors, copy constructors, copy assignment operator, or destructor.

    Example

    // __value_classes2.cpp
    // compile with: /clr /LD
    #using <mscorlib.dll>
    struct S1 {
       int i;
       void f();   // non-static (instance) method
    };
    
    struct S2 {
       int i;
       static void f();   // static method
    };
    
    __value class M {
    public:
       S1 *pS1;   // ok: pointer-to 
       S1 s1;   // ok: object of unmanaged POD type
       S2 s2;   // ok: object of unmanaged POD type 
    };
    
  • A __value class object can be allocated on the runtime stack. If it is embedded in a __gc object, it can also be allocated on the common language runtime heap.
  • Explicit allocation of memory on the C++ heap for an object of a __value class must be done with __nogc new only.
  • If no default constructor is defined for a __value class, all of its data members are initialized to zero by default.

The semantics of constructors in __value classes differs from C++ for interoperability reasons. If a constructor is declared, the default constructor can still be called.

// __value_classes3.cpp
// compile with: /clr
#using <mscorlib.dll>
using namespace System;
__value class G {
public:
   G(int i) { grains = i; }
   void update_grains(int i) { grains = i; }
   int show_grains() { return grains; }

private:
   int grains;
};

int main() {
   G g;   // C++ would not allow this
   g.update_grains(2);
   Console::WriteLine(g.show_grains());
}

Output

2

Constraints

The following apply to __value classes.

  • A __value class shall not inherit from an unmanaged class.
  • A __value class shall not have an unmanaged class derived from it.
  • A __value class does not support class inheritance. However, a __value class can inherit from one or more __gc interfaces.
  • A __value class shall not declare a user-defined copy constructor.
  • A __value class shall not declare or define friend classes or functions.
  • A __value class shall not declare or define a new or delete operator.
  • A __value class shall not contain a using declaration.
  • The calling convention of a member function of a __value class cannot be redefined to a native C++ calling convention, for example, to __cdecl.

    Example

    #using <mscorlib.dll>
    using namespace System;
    
    __gc __interface I {
       void f(int);
    };
    
    __value struct D: I {
       using I::f;   // C3182
       void f(char) { f(2); };
    };
    
  • A __value class shall not have the sizeof or offsetof operators applied to it. For versioning to work, client code must not hard-code data about the size of a managed object.
  • A __value class shall not have member functions with const or volatile modifiers.

    Example

    // __value_classes4.cpp
    // compile with: /clr
    #using <mscorlib.dll>
    __value struct A {
       void f() const {}  // C3842
    };
    
  • A __value class shall not declare a data member of whose type is an interior pointer subtype (see also Section 7.4). This constraint includes any subtypes.

    Example

    // __value_classes5.cpp
    // compile with: /clr
    #using <mscorlib.dll>
    using namespace System;
    __value struct A {
       Int32 __gc * k;  // C3160
       Int32 __gc * __nogc * l;   // C3166
       String  __gc * __gc * __nogc * __nogc * s;   // C3166
    };
    
  • A __value class shall only inherit from __gc interfaces. It shall not inherit from __gc classes or other __value classes, including System::Object.
  • A __value class shall not introduce any virtual methods. It shall only override methods of System::ValueType.
  • A __value class shall not be a base class and is therefore implicitly sealed (Section 18). The __sealed keyword is allowed on value classes, but is not required.
  • A __value class type shall not be the argument type of __gc new. However, an object of a __value class can exist in the common language runtime heap via embedding in a __gc object, or boxing.
Show:
© 2015 Microsoft