This documentation is archived and is not being maintained.

4 __gc Classes

Visual Studio .NET 2003

The keyword __gc on a class or struct indicates that it is garbage-collected, and its lifetime is managed by the common language runtime. No explicit calls to delete are required in the user program.

Example

// __gc_classes.cpp
// compile with: /clr
#using <mscorlib.dll>
__gc class G {
public:
   int k;
   int sum(int);
};

G::sum(int i) { return i * (i + 1) / 2; }

int main() {
   G * g = new G;
   System::Console::WriteLine(g->sum(4));
}

Output

10

Example

#using <mscorlib.dll>
using namespace System;
__gc class M {
public:
   int i;
};

int main() {
   while(true) {
      M *m = new M; // runs forever without exhausting heap
   }
}

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

Characteristics

  • A declaration of a __gc class shall always have the __gc keyword.
  • A __gc class can have a data member that has type pointer-to any unmanaged type.
  • A __gc class can contain a user-defined destructor (Section 4.2).
  • Operator delete can be called on a pointer-to a __gc class in order to force the destructor to run immediately (Section 4.2).
  • A __gc class can implement any number of __gc interfaces (Section 6).
  • A __gc class can contain properties (Section 13).
  • A __gc class can be marked with the __abstract keyword (Section 17).
  • A __gc class can be marked as "sealed" (Section 18).
  • A __gc class can declare a static class constructor (Section 19).
  • A __gc class can declare a constructor.
  • A __gc class can have a visibility specifier (Section 21.1).
  • A __gc 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 virtual functions, base classes, or user-defined constructors, copy constructors, copy assignment operator, or destructor.
  • By default, a __gc class is not visible outside its assembly. To make a __gc class visible outside its assembly, use the public access modifier (public __gc MyClass). For more information, see Class Visibility.

    Example

    // __gc_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
    };
    
    __gc class M {
    public:
       S1 *pS1;   // ok: pointer-to 
       S1 s1;     // ok: object of unmanaged POD type
       S2 s2;     // ok: object of unmanaged POD type 
    };
    

Constraints

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

    Example

    // __gc_classes3.cpp
    // compile with: /clr
    #using <mscorlib.dll>
    __gc struct B {
       void f(int);
    };
    
    __gc struct D: B {
       using B::f;   // C3182
       void f(char) { f(2); };
    };
    
  • A __gc 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 __gc class shall not have member functions with const or volatile modifiers.

    Example

    // __gc_classes4.cpp
    // compile with: /clr
    #using <mscorlib.dll>
    __gc class A {
    public:
       int f() const { return 1; }   // C3842
    };
    
  • A __gc 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

    #using <mscorlib.dll>
    __gc class A {
    public:
       Int32 __gc * k;   // error
       Int32 __gc * __nogc * l;   // error
       String  __gc * __gc * __nogc * __nogc * s;   // error
    };
    
  • A __gc class shall declare no more than one base __gc class. If no base class is specified, it is assumed to be the .NET Framework root class System::Object.
  • All objects of __gc class shall be created on the common language runtime's garbage-collected heap using the built-in operator new. Therefore, no object declaration, parameter declaration, or function return shall have __gc class type. Only pointer-to is allowed.

    Example

    // __gc_classes5.cpp
    // compile with: /clr
    // C3149 expected
    #using <mscorlib.dll>
    
    using System::String;
    __gc class M {
       String s1;   // error
       String *s2;   // ok
       String f1();   // error
       String * f2();   // ok
       void g1(String s);   // error
       void g2(String * s);   // ok
    };
    
  • Operator delete shall not be called on a pointer to an object of a __gc class that has no user-defined destructor.
  • A __gc class shall not override operator& or operator new.
  • The __gc and __nogc keywords shall not be used to qualify an unmanaged class in an object declaration.

    Example

    // __gc_classes6.cpp
    // compile with: /clr
    // C3150 expected
    #using <mscorlib.dll>
    // unmanaged class
    struct X { int i; };
    
    int main() {
       __gc X *x;   // error
    }
    
  • The __gc keyword shall not appear with the union keyword.

Unions are implemented by using the StructLayout and FieldOffset attributes.

Example

// __gc_classes7.cpp
// compile with: /clr
#using <mscorlib.dll> 
using System::Console;
using namespace System::Runtime::InteropServices;

[ StructLayout(LayoutKind::Explicit) ]
public __value struct MyUnion {
   [FieldOffset(0)] int a;
   [FieldOffset(0)] char c __nogc[4];
};

int main() {
   MyUnion m;
   m.a = 0x01020304;
   Console::Write(m.c[0]);
   Console::Write(m.c[1]);
   Console::Write(m.c[2]);
   Console::WriteLine(m.c[3]);
}

Output

4321
Show: