Gewusst wie: Definieren und Verwenden von Delegaten (C++/CLI)

In diesem Artikel, wie Delegaten in C++/CLI definiert und nutzt.

Obwohl .NET Framework stellt mehrere Delegaten, manchmal müssen Sie möglicherweise neue Delegaten definieren.

Das folgende Codebeispiel definiert einen Delegaten, der MyCallback genannt wird.Die Ereignisbehandlungscode-dfunktion, die aufgerufen wird, wenn dieser neue Delegat ist, ausgelöste-muss einen Rückgabetyp void haben und einen Verweis String akzeptieren.

Die Hauptfunktion verwendet eine statische Methode, die von SomeClass definiert wird, um den MyCallback Delegaten zu instanziieren.Der Delegat wird dann eine alternative Methode des Aufrufens dieser Funktion, wie dargestellt, indem die "einzelne" Zeichenfolge zum Delegatobjekt sendet.Nachfolgende, zusätzliche Instanzen von MyCallback werden zusammengefügt ausgeführt und anschließend durch einen Aufruf an den Delegatobjekt.

// use_delegate.cpp
// compile with: /clr
using namespace System;

ref class SomeClass
{
public:
   static void Func(String^ str)
   {
      Console::WriteLine("static SomeClass::Func - {0}", str);
   }
};

ref class OtherClass
{
public:
   OtherClass( Int32 n ) 
   {
      num = n;
   }

   void Method(String^ str) 
   {
      Console::WriteLine("OtherClass::Method - {0}, num = {1}", 
         str, num);
   }

   Int32 num;
};

delegate void MyCallback(String^ str);

int main( ) 
{
   MyCallback^ callback = gcnew MyCallback(SomeClass::Func);   
   callback("single"); 

   callback += gcnew MyCallback(SomeClass::Func);   

   OtherClass^ f = gcnew OtherClass(99);
   callback += gcnew MyCallback(f, &OtherClass::Method);

   f = gcnew OtherClass(100);
   callback += gcnew MyCallback(f, &OtherClass::Method);

   callback("chained");

   return 0;
}

Ausgabe

  

Im folgenden Codebeispiel wird gezeigt, wie ein Delegat mit einem Member einer Wertklasse zuordnet.

// mcppv2_del_mem_value_class.cpp
// compile with: /clr
using namespace System;
public delegate void MyDel();

value class A {
public:
   void func1() {
      Console::WriteLine("test");
   }
};

int main() {
   A a;
   A^ ah = a;
   MyDel^ f = gcnew MyDel(a, &A::func1);   // implicit box of a
   f();
   MyDel^ f2 = gcnew MyDel(ah, &A::func1);
   f2();
}

Ausgabe

  

Verwenden von Delegaten zusammengesetzt

Sie können den "-" Operator verwenden, um einen Mithilfe von einem zusammengesetzten Delegaten entfernen.

// mcppv2_compose_delegates.cpp
// compile with: /clr
using namespace System;

delegate void MyDelegate(String ^ s);

ref class MyClass {
public:
   static void Hello(String ^ s) {
      Console::WriteLine("Hello, {0}!", s);
   }

   static void Goodbye(String ^ s) {
      Console::WriteLine("  Goodbye, {0}!", s);
   }
};

int main() {

   MyDelegate ^ a = gcnew MyDelegate(MyClass::Hello);
   MyDelegate ^ b = gcnew MyDelegate(MyClass::Goodbye);
   MyDelegate ^ c = a + b;
   MyDelegate ^ d = c - a;

   Console::WriteLine("Invoking delegate a:");
   a("A");
   Console::WriteLine("Invoking delegate b:");
   b("B");
   Console::WriteLine("Invoking delegate c:");
   c("C");
   Console::WriteLine("Invoking delegate d:");
   d("D");
}

Ausgabe

  
  
  
  
  

Führen Sie ein delegate^ an eine systemeigene Funktion, die einen Funktionszeiger erwartet

Von einer verwalteten Komponente können Sie eine systemeigene Funktion mit Funktionszeigerparametern aufrufen, in denen die systemeigene Funktion die - Memberfunktion des verwalteten Delegaten der Komponente dann aufrufen kann.

Dieses Beispiel erstellt die DLL-, das die systemeigene Funktion exportiert:

// delegate_to_native_function.cpp
// compile with: /LD
#include < windows.h >
extern "C" {
   __declspec(dllexport)
   void nativeFunction(void (CALLBACK *mgdFunc)(const char* str)) {
      mgdFunc("Call to Managed Function");
   }
}

Im folgenden Beispiel wird die DLL-Datei und führt ein Delegathandle die systemeigene Funktion, die einen Funktionszeiger erwartet.

// delegate_to_native_function_2.cpp
// compile with: /clr
using namespace System;
using namespace System::Runtime::InteropServices;

delegate void Del(String ^s);
public ref class A {
public:
   void delMember(String ^s) {
      Console::WriteLine(s);
   }
};

[DllImportAttribute("delegate_to_native_function", CharSet=CharSet::Ansi)]
extern "C" void nativeFunction(Del ^d);

int main() {
   A ^a = gcnew A;
   Del ^d = gcnew Del(a, &A::delMember);
   nativeFunction(d);   // Call to native function
}

Ausgabe

  

So Delegaten mit nicht verwalteten Funktionen zuordnen

Um einen Delegaten mit einer systemeigenen Funktion zuzuordnen, müssen Sie die systemeigene Funktion in einem verwalteten Typ umschließen und die von PInvoke aufgerufen werden Funktion deklarieren.

// mcppv2_del_to_umnangd_func.cpp
// compile with: /clr
#pragma unmanaged
extern "C" void printf(const char*, ...);
class A {
public:
   static void func(char* s) {
      printf(s);
   }
};

#pragma managed
public delegate void func(char*); 

ref class B {
   A* ap;

public:
   B(A* ap):ap(ap) {}
   void func(char* s) {
      ap->func(s); 
   }
};

int main() {
   A* a = new A;
   B^ b = gcnew B(a);
   func^ f = gcnew func(b, &B::func);
   f("hello");
   delete a;
}

Ausgabe

  

So fügen Sie ungebundene Delegaten verwenden

Sie können einen ungebundenen Delegaten verwenden, um eine Instanz des Typs zu übergeben, dessen Funktion Sie aufrufen möchten, wenn der Delegat aufgerufen wird.

Ungebundene Delegaten sind besonders nützlich, wenn Sie durch die Objekte in einem Auflistung-durch die Anwendung von für jedes in durchlaufen Schlüsselwort- und eine Memberfunktion auf jeder Instanz aufrufen möchten.

Im Folgenden wird gezeigt, wie Grenze und ungebundene Delegaten deklariert, instanziiert und aufruft:

Aktion

Grenzen-Delegaten

Ungebundene Delegaten

Declare

Die Delegate-Signatur muss die Signatur der Funktion übereinstimmen, die Sie über den Delegaten aufrufen möchten.

Der erste Parameter der Signatur des Delegaten ist der Typ von this für das Objekt, das Sie aufrufen möchten.

Nach dem ersten Parameter muss die Delegate-Signatur die Signatur der Funktion übereinstimmen, die Sie über den Delegaten aufrufen möchten.

Instanziieren Sie

Wenn Sie einen gebundenen Delegaten instanziiert, können Sie eine Instanzfunktion angeben oder eine globale oder statische Memberfunktion.

Um eine Instanzfunktion anzugeben, ist der erste Parameter eine Instanz des Typs Sie dessen - Memberfunktion aufrufen möchten und der zweite Parameter die Adresse der Funktion ist, die Sie aufrufen möchten.

Wenn Sie eine globale oder statische Memberfunktion aufrufen möchten, führen Sie einfach den Namen einer globalen Funktion oder den Namen der statischen Memberfunktion.

Wenn Sie einen ungebundenen Delegaten instanziiert, führen Sie einfach die Adresse der Funktion, die Sie aufrufen möchten.

Call

Wenn Sie einen gebundenen Delegaten aufrufen, führen Sie einfach die Parameter, die von der Delegate-Signatur erforderlich sind.

Identisch mit ein gebundener Delegat, aber beachten daran, dass der erste Parameter eine Instanz des Objekts sein muss, das die Funktion enthält, die Sie aufrufen möchten.

Dieses Beispiel zeigt, wie Sie ungebundene Delegaten deklariert, instanziiert und aufruft:

// unbound_delegates.cpp
// compile with: /clr
ref struct A {
   A(){}
   A(int i) : m_i(i) {}
   void Print(int i) { System::Console::WriteLine(m_i + i);}

private:
   int m_i;
};

value struct V {
   void Print() { System::Console::WriteLine(m_i);}
   int m_i;
};

delegate void Delegate1(A^, int i);
delegate void Delegate2(A%, int i);

delegate void Delegate3(interior_ptr<V>);
delegate void Delegate4(V%);

delegate void Delegate5(int i);
delegate void Delegate6();

int main() {
   A^ a1 = gcnew A(1);
   A% a2 = *gcnew A(2);

   Delegate1 ^ Unbound_Delegate1 = gcnew Delegate1(&A::Print);
   // delegate takes a handle
   Unbound_Delegate1(a1, 1);
   Unbound_Delegate1(%a2, 1);

   Delegate2 ^ Unbound_Delegate2 = gcnew Delegate2(&A::Print);
   // delegate takes a tracking reference (must deference the handle)
   Unbound_Delegate2(*a1, 1);
   Unbound_Delegate2(a2, 1);

   // instantiate a bound delegate to an instance member function
   Delegate5 ^ Bound_Del = gcnew Delegate5(a1, &A::Print);
   Bound_Del(1);

   // instantiate value types
   V v1 = {7};
   V v2 = {8};

   Delegate3 ^ Unbound_Delegate3 = gcnew Delegate3(&V::Print);
   Unbound_Delegate3(&v1);
   Unbound_Delegate3(&v2);

   Delegate4 ^ Unbound_Delegate4 = gcnew Delegate4(&V::Print);
   Unbound_Delegate4(v1);
   Unbound_Delegate4(v2);

   Delegate6 ^ Bound_Delegate3 = gcnew Delegate6(v1, &V::Print);
   Bound_Delegate3();
}

Ausgabe

  

Das folgende Beispiel zeigt, wie ungebundene Delegaten und die für jedes in Schlüsselwörter verwendet, um Objekte in einer Auflistung durchlaufen und eine Memberfunktion auf jeder Instanz aufzurufen.

// unbound_delegates_2.cpp
// compile with: /clr
using namespace System;

ref class RefClass {
   String^ _Str;

public:
   RefClass( String^ str ) : _Str( str ) {}
   void Print() { Console::Write( _Str ); }
};

delegate void PrintDelegate( RefClass^ );

int main() {
   PrintDelegate^ d = gcnew PrintDelegate( &RefClass::Print );

   array< RefClass^ >^ a = gcnew array<RefClass^>( 10 );

   for ( int i = 0; i < a->Length; ++i )
      a[i] = gcnew RefClass( i.ToString() );

   for each ( RefClass^ R in a )
      d( R );

   Console::WriteLine();
}

Dieses Beispiel stellt einen ungebundenen Delegaten an den Accessorfunktionen einer Eigenschaft erstellt:

// unbound_delegates_3.cpp
// compile with: /clr
ref struct B {
   property int P1 {
      int get() { return m_i; }
      void set(int i) { m_i = i; }
   }

private:
   int m_i;
};

delegate void DelBSet(B^, int);
delegate int DelBGet(B^);

int main() {
   B^ b = gcnew B;

   DelBSet^ delBSet = gcnew DelBSet(&B::P1::set);
   delBSet(b, 11);

   DelBGet^ delBGet = gcnew DelBGet(&B::P1::get);   
   System::Console::WriteLine(delBGet(b));
}

Ausgabe

  

Das folgende Beispiel zeigt, wie ein Multicastdelegaten Delegaten, in dem eine - Instanz gebunden und eine Instanz handelt, wird ungebunden aufruft.

// unbound_delegates_4.cpp
// compile with: /clr
ref class R {
public:
   R(int i) : m_i(i) {}

   void f(R ^ r) {
      System::Console::WriteLine("in f(R ^ r)");
   }

   void f() {
      System::Console::WriteLine("in f()");
   }

private:
   int m_i;
};

delegate void Del(R ^);

int main() {
   R ^r1 = gcnew R(11);
   R ^r2 = gcnew R(12);

   Del^ d = gcnew Del(r1, &R::f);
   d += gcnew Del(&R::f);
   d(r2);
};

Ausgabe

  

Das folgende Beispiel zeigt, wie ein ungebundenen generischen Delegaten erstellt und aufruft.

// unbound_delegates_5.cpp
// compile with: /clr
ref struct R {
   R(int i) : m_i(i) {}

   int f(R ^) { return 999; }
   int f() { return m_i + 5; }
   
   int m_i;
};

value struct V {
   int f(V%) { return 999; }
   int f() { return m_i + 5; } 

   int m_i;
};

generic <typename T>
delegate int Del(T t);

generic <typename T>
delegate int DelV(T% t);


int main() {   
   R^ hr = gcnew R(7);
   System::Console::WriteLine((gcnew Del<R^>(&R::f))(hr));

   V v;
   v.m_i = 9;
   System::Console::WriteLine((gcnew DelV<V >(&V::f))(v) );
}

Ausgabe

  

Siehe auch

Referenz

Delegat