Marshalling predefinito per i delegati
Per un delegato gestito, il marshalling viene eseguito come interfaccia COM o puntatore a funzione, in base al meccanismo di chiamata:
Con il richiamo piattaforma, per impostazione predefinita il marshalling di un delegato viene eseguito come puntatore a funzione non gestito.
Con l'interoperabilità COM, per impostazione predefinita il marshalling di un delegato viene eseguito come interfaccia COM di tipo _Delegate. L'interfaccia _Delegate è definita nella libreria dei tipi Mscorlib.tlb e contiene il metodo Delegate.DynamicInvoke, che consente di chiamare il metodo al quale fa riferimento il delegato.
Nella tabella seguente vengono mostrate le opzioni di marshalling per il tipo di dati del delegato gestito. L'attributo MarshalAsAttribute fornisce numerosi valori dell'enumerazione UnmanagedType per il marshalling di delegati.
Tipo di enumerazione | Descrizione del formato non gestito |
---|---|
UnmanagedType.FunctionPtr |
Puntatore a funzione non gestito. |
UnmanagedType.Interface |
Interfaccia di tipo _Delegate, come definito in Mscorlib.tlb. |
Nell'esempio riportato di seguito i metodi di DelegateTestInterface
sono esportati in una libreria dei tipi COM. Si noti che solo i delegati contrassegnati con la parola chiave ref (o ByRef) vengono passati come parametri In/Out.
using System;
using System.Runtime.InteropServices;
public interface DelegateTest {
void m1(Delegate d);
void m2([MarshalAs(UnmanagedType.Interface)] Delegate d);
void m3([MarshalAs(UnmanagedType.Interface)] ref Delegate d);
void m4([MarshalAs(UnmanagedType.FunctionPtr)] Delegate d);
void m5([MarshalAs(UnmanagedType.FunctionPtr)] ref Delegate d);
}
Rappresentazione di libreria dei tipi
importlib("mscorlib.tlb");
interface DelegateTest : IDispatch {
[id(…)] HRESULT m1([in] _Delegate* d);
[id(…)] HRESULT m2([in] _Delegate* d);
[id(…)] HRESULT m3([in, out] _Delegate** d);
[id()] HRESULT m4([in] int d);
[id()] HRESULT m5([in, out] int *d);
};
È possibile annullare i riferimenti a un puntatore a funzione, proprio come per qualsiasi altro puntatore a funzione non gestito.
Nota
Un riferimento al puntatore a funzione di un delegato gestito nel codice non gestito non impedisce l'esecuzione della procedura di Garbage Collection sull'oggetto gestito in Common Language Runtime.
Il codice riportato di seguito, ad esempio, non è corretto, in quanto il riferimento all'oggetto cb
, passato al metodo SetChangeHandler
, non conserva cb
oltre la durata del metodo Test
. Una volta che l'oggetto cb
viene raccolto nel Garbage Collector, il puntatore a funzione passato a SetChangeHandler
non è più valido.
public class ExternalAPI {
[DllImport("External.dll")]
public static extern void SetChangeHandler(
[MarshalAs(UnmanagedType.FunctionPtr)]ChangeDelegate d);
}
public delegate bool ChangeDelegate([MarshalAs(UnmanagedType.LPWStr) string S);
public class CallBackClass {
public bool OnChange(string S){ return true;}
}
internal class DelegateTest {
public static void Test() {
CallBackClass cb = new CallBackClass();
// Caution: The following reference on the cb object does not keep the
// object from being garbage collected after the Main method
// executes.
ExternalAPI.SetChangeHandler(new ChangeDelegate(cb.OnChange));
}
}
Per compensare l'inaspettata operazione di Garbage Collection, il chiamante deve assicurarsi che l'oggetto cb
venga mantenuto per tutto il tempo in cui il puntatore a funzione non gestito è in uso. Se lo si desidera, è possibile far sì che il codice non gestito comunichi al codice gestito quando il puntatore a funzione non è più necessario, come nell'esempio riportato di seguito.
internal class DelegateTest {
CallBackClass cb;
// Called before ever using the callback function.
public static void SetChangeHandler() {
cb = new CallBackClass();
ExternalAPI.SetChangeHandler(new ChangeDelegate(cb.OnChange));
}
// Called after using the callback function for the last time.
public static void RemoveChangeHandler() {
// The cb object can be collected now. The unmanaged code is
// finished with the callback function.
cb = null;
}
}
Vedere anche
Concetti
Tipi copiabili e non copiabili
Attributi direzionali
Copia e blocco