Méthodes System.Delegate.CreateDelegate

Cet article vous offre des remarques complémentaires à la documentation de référence pour cette API.

Les CreateDelegate méthodes créent un délégué d’un type spécifié.

Méthode CreateDelegate(Type, MethodInfo)

Cette surcharge de méthode équivaut à appeler la CreateDelegate(Type, MethodInfo, Boolean) surcharge de méthode et à true spécifier pour throwOnBindFailure.

Exemples

Cette section contient deux exemples de code. Le premier exemple illustre les deux types de délégués qui peuvent être créés avec cette surcharge de méthode : ouvrir sur une méthode d’instance et ouvrir sur une méthode statique.

Le deuxième exemple de code illustre les types de paramètres compatibles et les types de retour.

Exemple 1

L’exemple de code suivant illustre les deux façons dont un délégué peut être créé à l’aide de cette surcharge de la CreateDelegate méthode.

Remarque

Il existe deux surcharges de la CreateDelegate méthode qui spécifient un MethodInfo mais pas un premier argument ; leur fonctionnalité est identique, sauf que l’on vous permet de spécifier s’il faut lever en cas de défaillance de liaison, et l’autre lève toujours. Cet exemple de code utilise les deux surcharges.

L’exemple déclare une classe C avec une méthode statique et une méthode M2M1d’instance, et deux types délégués : D1 prend une instance et C une chaîne, et D2 prend une chaîne.

Une deuxième classe nommée Example contient le code qui crée les délégués.

  • Un délégué de type D1, représentant une méthode d’instance ouverte, est créé pour la méthode M1d’instance . Une instance doit être passée lorsque le délégué est appelé.
  • Un délégué de type D2, représentant une méthode statique ouverte, est créé pour la méthode M2statique .
using System;
using System.Reflection;

// Declare three delegate types for demonstrating the combinations
// of static versus instance methods and open versus closed
// delegates.
//
public delegate void D1(C c, string s);
public delegate void D2(string s);
public delegate void D3();

// A sample class with an instance method and a static method.
//
public class C
{
    private int id;
    public C(int id) { this.id = id; }

    public void M1(string s)
    {
        Console.WriteLine("Instance method M1 on C:  id = {0}, s = {1}",
            this.id, s);
    }

    public static void M2(string s)
    {
        Console.WriteLine("Static method M2 on C:  s = {0}", s);
    }
}

public class Example2
{
    public static void Main()
    {
        C c1 = new C(42);

        // Get a MethodInfo for each method.
        //
        MethodInfo mi1 = typeof(C).GetMethod("M1",
            BindingFlags.Public | BindingFlags.Instance);
        MethodInfo mi2 = typeof(C).GetMethod("M2",
            BindingFlags.Public | BindingFlags.Static);

        D1 d1;
        D2 d2;
        D3 d3;

        Console.WriteLine("\nAn instance method closed over C.");
        // In this case, the delegate and the
        // method must have the same list of argument types; use
        // delegate type D2 with instance method M1.
        //
        Delegate test =
            Delegate.CreateDelegate(typeof(D2), c1, mi1, false);

        // Because false was specified for throwOnBindFailure
        // in the call to CreateDelegate, the variable 'test'
        // contains null if the method fails to bind (for
        // example, if mi1 happened to represent a method of
        // some class other than C).
        //
        if (test != null)
        {
            d2 = (D2)test;

            // The same instance of C is used every time the
            // delegate is invoked.
            d2("Hello, World!");
            d2("Hi, Mom!");
        }

        Console.WriteLine("\nAn open instance method.");
        // In this case, the delegate has one more
        // argument than the instance method; this argument comes
        // at the beginning, and represents the hidden instance
        // argument of the instance method. Use delegate type D1
        // with instance method M1.
        //
        d1 = (D1)Delegate.CreateDelegate(typeof(D1), null, mi1);

        // An instance of C must be passed in each time the
        // delegate is invoked.
        //
        d1(c1, "Hello, World!");
        d1(new C(5280), "Hi, Mom!");

        Console.WriteLine("\nAn open static method.");
        // In this case, the delegate and the method must
        // have the same list of argument types; use delegate type
        // D2 with static method M2.
        //
        d2 = (D2)Delegate.CreateDelegate(typeof(D2), null, mi2);

        // No instances of C are involved, because this is a static
        // method.
        //
        d2("Hello, World!");
        d2("Hi, Mom!");

        Console.WriteLine("\nA static method closed over the first argument (String).");
        // The delegate must omit the first argument of the method.
        // A string is passed as the firstArgument parameter, and
        // the delegate is bound to this string. Use delegate type
        // D3 with static method M2.
        //
        d3 = (D3)Delegate.CreateDelegate(typeof(D3),
            "Hello, World!", mi2);

        // Each time the delegate is invoked, the same string is
        // used.
        d3();
    }
}

/* This code example produces the following output:

An instance method closed over C.
Instance method M1 on C:  id = 42, s = Hello, World!
Instance method M1 on C:  id = 42, s = Hi, Mom!

An open instance method.
Instance method M1 on C:  id = 42, s = Hello, World!
Instance method M1 on C:  id = 5280, s = Hi, Mom!

An open static method.
Static method M2 on C:  s = Hello, World!
Static method M2 on C:  s = Hi, Mom!

A static method closed over the first argument (String).
Static method M2 on C:  s = Hello, World!
 */
open System
open System.Reflection

// A sample class with an instance method and a static method.
type C(id) =
    member _.M1(s) =
        printfn $"Instance method M1 on C:  id = %i{id}, s = %s{s}"

    static member M2(s) =
        printfn $"Static method M2 on C:  s = %s{s}"
    
// Declare three delegate types for demonstrating the combinations
// of static versus instance methods and open versus closed
// delegates.
type D1 = delegate of C * string -> unit
type D2 = delegate of string -> unit
type D3 = delegate of unit -> unit

let c1 = C 42

// Get a MethodInfo for each method.
//
let mi1 = typeof<C>.GetMethod("M1", BindingFlags.Public ||| BindingFlags.Instance)
let mi2 = typeof<C>.GetMethod("M2", BindingFlags.Public ||| BindingFlags.Static)

printfn "\nAn instance method closed over C."

// In this case, the delegate and the
// method must have the same list of argument types use
// delegate type D2 with instance method M1.
let test = Delegate.CreateDelegate(typeof<D2>, c1, mi1, false)

// Because false was specified for throwOnBindFailure
// in the call to CreateDelegate, the variable 'test'
// contains null if the method fails to bind (for
// example, if mi1 happened to represent a method of
// some class other than C).
if test <> null then
    let d2 = test :?> D2

    // The same instance of C is used every time the
    // delegate is invoked.
    d2.Invoke "Hello, World!"
    d2.Invoke "Hi, Mom!"

printfn "\nAn open instance method."

// In this case, the delegate has one more
// argument than the instance method this argument comes
// at the beginning, and represents the hidden instance
// argument of the instance method. Use delegate type D1
// with instance method M1.
let d1 = Delegate.CreateDelegate(typeof<D1>, null, mi1) :?> D1

// An instance of C must be passed in each time the
// delegate is invoked.
d1.Invoke(c1, "Hello, World!")
d1.Invoke(C 5280, "Hi, Mom!")

printfn "\nAn open static method."
// In this case, the delegate and the method must
// have the same list of argument types use delegate type
// D2 with static method M2.
let d2 = Delegate.CreateDelegate(typeof<D2>, null, mi2) :?> D2

// No instances of C are involved, because this is a static
// method.
d2.Invoke "Hello, World!"
d2.Invoke "Hi, Mom!"

printfn "\nA static method closed over the first argument (String)."
// The delegate must omit the first argument of the method.
// A string is passed as the firstArgument parameter, and
// the delegate is bound to this string. Use delegate type
// D3 with static method M2.
let d3 = Delegate.CreateDelegate(typeof<D3>, "Hello, World!", mi2) :?> D3

// Each time the delegate is invoked, the same string is used.
d3.Invoke()

// This code example produces the following output:
//     An instance method closed over C.
//     Instance method M1 on C:  id = 42, s = Hello, World!
//     Instance method M1 on C:  id = 42, s = Hi, Mom!
//     
//     An open instance method.
//     Instance method M1 on C:  id = 42, s = Hello, World!
//     Instance method M1 on C:  id = 5280, s = Hi, Mom!
//     
//     An open static method.
//     Static method M2 on C:  s = Hello, World!
//     Static method M2 on C:  s = Hi, Mom!
//     
//     A static method closed over the first argument (String).
//     Static method M2 on C:  s = Hello, World!
Imports System.Reflection
Imports System.Security.Permissions

' Declare three delegate types for demonstrating the combinations
' of Shared versus instance methods and open versus closed
' delegates.
'
Public Delegate Sub D1(ByVal c As C2, ByVal s As String)
Public Delegate Sub D2(ByVal s As String)
Public Delegate Sub D3()

' A sample class with an instance method and a Shared method.
'
Public Class C2
    Private id As Integer
    Public Sub New(ByVal id As Integer)
        Me.id = id
    End Sub

    Public Sub M1(ByVal s As String)
        Console.WriteLine("Instance method M1 on C2:  id = {0}, s = {1}",
            Me.id, s)
    End Sub

    Public Shared Sub M2(ByVal s As String)
        Console.WriteLine("Shared method M2 on C2:  s = {0}", s)
    End Sub
End Class

Public Class Example2

    Public Shared Sub Main()

        Dim c1 As New C2(42)

        ' Get a MethodInfo for each method.
        '
        Dim mi1 As MethodInfo = GetType(C2).GetMethod("M1",
            BindingFlags.Public Or BindingFlags.Instance)
        Dim mi2 As MethodInfo = GetType(C2).GetMethod("M2",
            BindingFlags.Public Or BindingFlags.Static)

        Dim d1 As D1
        Dim d2 As D2
        Dim d3 As D3


        Console.WriteLine(vbLf & "An instance method closed over C2.")
        ' In this case, the delegate and the
        ' method must have the same list of argument types; use
        ' delegate type D2 with instance method M1.
        '
        Dim test As [Delegate] =
            [Delegate].CreateDelegate(GetType(D2), c1, mi1, False)

        ' Because False was specified for throwOnBindFailure 
        ' in the call to CreateDelegate, the variable 'test'
        ' contains Nothing if the method fails to bind (for 
        ' example, if mi1 happened to represent a method of 
        ' some class other than C2).
        '
        If test IsNot Nothing Then
            d2 = CType(test, D2)

            ' The same instance of C2 is used every time the
            ' delegate is invoked.
            d2("Hello, World!")
            d2("Hi, Mom!")
        End If


        Console.WriteLine(vbLf & "An open instance method.")
        ' In this case, the delegate has one more 
        ' argument than the instance method; this argument comes
        ' at the beginning, and represents the hidden instance
        ' argument of the instance method. Use delegate type D1
        ' with instance method M1.
        '
        d1 = CType([Delegate].CreateDelegate(GetType(D1), Nothing, mi1), D1)

        ' An instance of C2 must be passed in each time the 
        ' delegate is invoked.
        '
        d1(c1, "Hello, World!")
        d1(New C2(5280), "Hi, Mom!")


        Console.WriteLine(vbLf & "An open Shared method.")
        ' In this case, the delegate and the method must 
        ' have the same list of argument types; use delegate type
        ' D2 with Shared method M2.
        '
        d2 = CType([Delegate].CreateDelegate(GetType(D2), Nothing, mi2), D2)

        ' No instances of C2 are involved, because this is a Shared
        ' method. 
        '
        d2("Hello, World!")
        d2("Hi, Mom!")


        Console.WriteLine(vbLf & "A Shared method closed over the first argument (String).")
        ' The delegate must omit the first argument of the method.
        ' A string is passed as the firstArgument parameter, and 
        ' the delegate is bound to this string. Use delegate type 
        ' D3 with Shared method M2. 
        '
        d3 = CType([Delegate].CreateDelegate(GetType(D3), "Hello, World!", mi2), D3)

        ' Each time the delegate is invoked, the same string is
        ' used.
        d3()

    End Sub
End Class

' This code example produces the following output:
'
'An instance method closed over C2.
'Instance method M1 on C2:  id = 42, s = Hello, World!
'Instance method M1 on C2:  id = 42, s = Hi, Mom!
'
'An open instance method.
'Instance method M1 on C2:  id = 42, s = Hello, World!
'Instance method M1 on C2:  id = 5280, s = Hi, Mom!
'
'An open Shared method.
'Shared method M2 on C2:  s = Hello, World!
'Shared method M2 on C2:  s = Hi, Mom!
'
'A Shared method closed over the first argument (String).
'Shared method M2 on C2:  s = Hello, World!
'

Exemple 2

L’exemple de code suivant illustre la compatibilité des types de paramètres et des types de retour.

L’exemple de code définit une classe de base nommée Base et une classe nommée Derived qui dérive de Base. La classe dérivée a une static méthode (Shared en Visual Basic) nommée MyMethod avec un paramètre de type Base et un type de retour de Derived. L’exemple de code définit également un délégué nommé Example qui a un paramètre de type Derived et un type de retour de Base.

L’exemple de code montre que le délégué nommé Example peut être utilisé pour représenter la méthode MyMethod. La méthode peut être liée au délégué, car :

  • Le type de paramètre du délégué (Derived) est plus restrictif que le type de paramètre (BaseMyMethod), de sorte qu’il est toujours sûr de passer l’argument du délégué à MyMethod.
  • Le type de retour (MyMethodDerived) est plus restrictif que le type de paramètre du délégué (Base), de sorte qu’il est toujours sûr de convertir le type de retour de la méthode en type de retour du délégué.

L’exemple de code ne produit aucune sortie.

using System;
using System.Reflection;

// Define two classes to use in the demonstration, a base class and
// a class that derives from it.
//
public class Base { }

public class Derived : Base
{
    // Define a static method to use in the demonstration. The method
    // takes an instance of Base and returns an instance of Derived.
    // For the purposes of the demonstration, it is not necessary for
    // the method to do anything useful.
    //
    public static Derived MyMethod(Base arg)
    {
        Base dummy = arg;
        return new Derived();
    }
}

// Define a delegate that takes an instance of Derived and returns an
// instance of Base.
//
public delegate Base Example5(Derived arg);

class Test
{
    public static void Main()
    {
        // The binding flags needed to retrieve MyMethod.
        BindingFlags flags = BindingFlags.Public | BindingFlags.Static;

        // Get a MethodInfo that represents MyMethod.
        MethodInfo minfo = typeof(Derived).GetMethod("MyMethod", flags);

        // Demonstrate contravariance of parameter types and covariance
        // of return types by using the delegate Example5 to represent
        // MyMethod. The delegate binds to the method because the
        // parameter of the delegate is more restrictive than the
        // parameter of the method (that is, the delegate accepts an
        // instance of Derived, which can always be safely passed to
        // a parameter of type Base), and the return type of MyMethod
        // is more restrictive than the return type of Example5 (that
        // is, the method returns an instance of Derived, which can
        // always be safely cast to type Base).
        //
        Example5 ex =
            (Example5)Delegate.CreateDelegate(typeof(Example5), minfo);

        // Execute MyMethod using the delegate Example5.
        //
        Base b = ex(new Derived());
    }
}
open System
open System.Reflection

// Define two classes to use in the demonstration, a base class and
// a class that derives from it.
type Base() = class end

type Derived() =
    inherit Base()

    // Define a static method to use in the demonstration. The method
    // takes an instance of Base and returns an instance of Derived.
    // For the purposes of the demonstration, it is not necessary for
    // the method to do anything useful.
    static member MyMethod(arg: Base) =
        Derived()

// Define a delegate that takes an instance of Derived and returns an
// instance of Base.
type Example = delegate of Derived -> Base

// The binding flags needed to retrieve MyMethod.
let flags = BindingFlags.Public ||| BindingFlags.Static

// Get a MethodInfo that represents MyMethod.
let minfo = typeof<Derived>.GetMethod("MyMethod", flags)

// Demonstrate contravariance of parameter types and covariance
// of return types by using the delegate Example to represent
// MyMethod. The delegate binds to the method because the
// parameter of the delegate is more restrictive than the
// parameter of the method (that is, the delegate accepts an
// instance of Derived, which can always be safely passed to
// a parameter of type Base), and the return type of MyMethod
// is more restrictive than the return type of Example (that
// is, the method returns an instance of Derived, which can
// always be safely cast to type Base).
let ex = Delegate.CreateDelegate(typeof<Example>, minfo) :?> Example

// Execute MyMethod using the delegate Example.
let b = Derived() |> ex.Invoke
Imports System.Reflection

' Define two classes to use in the demonstration, a base class and 
' a class that derives from it.
'
Public Class Base
End Class

Public Class Derived
    Inherits Base

    ' Define a Shared method to use in the demonstration. The method 
    ' takes an instance of Base and returns an instance of Derived.  
    ' For the purposes of the demonstration, it is not necessary for 
    ' the method to do anything useful. 
    '
    Public Shared Function MyMethod(ByVal arg As Base) As Derived
        Dim dummy As Base = arg
        Return New Derived()
    End Function

End Class

' Define a delegate that takes an instance of Derived and returns an
' instance of Base.
'
Public Delegate Function Example(ByVal arg As Derived) As Base

Module Test

    Sub Main()

        ' The binding flags needed to retrieve MyMethod.
        Dim flags As BindingFlags = _
            BindingFlags.Public Or BindingFlags.Static

        ' Get a MethodInfo that represents MyMethod.
        Dim minfo As MethodInfo = _
            GetType(Derived).GetMethod("MyMethod", flags)

        ' Demonstrate contravariance of parameter types and covariance
        ' of return types by using the delegate Example to represent
        ' MyMethod. The delegate binds to the method because the
        ' parameter of the delegate is more restrictive than the 
        ' parameter of the method (that is, the delegate accepts an
        ' instance of Derived, which can always be safely passed to
        ' a parameter of type Base), and the return type of MyMethod
        ' is more restrictive than the return type of Example (that
        ' is, the method returns an instance of Derived, which can
        ' always be safely cast to type Base). 
        '
        Dim ex As Example = CType( _
            [Delegate].CreateDelegate(GetType(Example), minfo), _
            Example _
        )

        ' Execute MyMethod using the delegate Example.
        '        
        Dim b As Base = ex(New Derived())
    End Sub
End Module

Méthodes CreateDelegate(Type, Object, MethodInfo) et CreateDelegate(Type, Object, MethodInfo, Boolean)

La fonctionnalité de ces deux surcharges est la même que celle qui vous permet de spécifier s’il faut lever en cas de défaillance de liaison, et l’autre lève toujours.

Le type délégué et la méthode doivent avoir des types de retour compatibles. Autrement dit, le type de retour de method doit être assignable au type de retour de type.

firstArgument, le deuxième paramètre de ces surcharges est le premier argument de la méthode que représente le délégué. S’il firstArgument est fourni, il est transmis à method chaque fois que le délégué est appelé ; firstArgument est dit lié au délégué, et le délégué est dit fermé sur son premier argument. Si c’est static (Shared en Visual Basic), la liste d’arguments fournie lors de l’appel du délégué inclut tous les paramètres sauf le premier ; s’il method s’agit d’une méthode d’instance, elle firstArgument est passée au paramètre d’instance masqué (représenté par this C#, ou en Me Visual method Basic).

S’il firstArgument est fourni, le premier paramètre de method doit être un type référence et firstArgument doit être compatible avec ce type.

Important

Si method c’est static (Shared en Visual Basic) et que son premier paramètre est de type Object ou ValueType, firstArgument peut être un type valeur. Dans ce cas firstArgument , il est automatiquement boxé. La boxe automatique ne se produit pas pour d’autres arguments, comme dans un appel de fonction C# ou Visual Basic.

S’il firstArgument s’agit d’une référence null et method est une méthode d’instance, le résultat dépend des signatures du type type délégué et de method:

  • Si la signature d’inclut type explicitement le premier paramètre masqué, methodle délégué est dit pour représenter une méthode d’instance ouverte. Lorsque le délégué est appelé, le premier argument de la liste d’arguments est passé au paramètre d’instance masqué de method.
  • Si les signatures et methodtype correspondances (autrement dit, tous les types de paramètres sont compatibles), le délégué est dit fermé sur une référence Null. Appeler le délégué est comme appeler une méthode d’instance sur une instance Null, ce qui n’est pas une chose particulièrement utile à faire.

S’il firstArgument s’agit d’une référence null et method est statique, le résultat dépend des signatures du type type délégué et de method:

  • Si la signature et type la correspondance (autrement dit, tous les types de method paramètres sont compatibles), le délégué est dit pour représenter une méthode statique ouverte. Il s’agit du cas le plus courant pour les méthodes statiques. Dans ce cas, vous pouvez obtenir des performances légèrement meilleures à l’aide de la CreateDelegate(Type, MethodInfo) surcharge de méthode.
  • Si la signature de type commence par le deuxième paramètre et method le reste des types de paramètres sont compatibles, le délégué est dit fermé sur une référence Null. Lorsque le délégué est appelé, une référence Null est passée au premier paramètre de method.

Exemple

L’exemple de code suivant montre toutes les méthodes qu’un type délégué unique peut représenter : fermée sur une méthode d’instance, ouverte sur une méthode d’instance, ouverte sur une méthode statique et fermée sur une méthode statique.

L’exemple de code définit deux classes et CF, et un type D délégué avec un argument de type C. Les classes ont des méthodes M1statiques et d’instance correspondantes, M3et M4la classe C a également une méthode M2 d’instance qui n’a aucun argument.

Une troisième classe nommée Example contient le code qui crée les délégués.

  • Les délégués sont créés pour la méthode M1 d’instance de type et de type CF; chacun est fermé sur une instance du type respectif. La méthode M1 de type C affiche les ID propriétés de l’instance liée et de l’argument.
  • Un délégué est créé pour la méthode M2 de type C. Il s’agit d’un délégué d’instance ouvert, dans lequel l’argument du délégué représente le premier argument masqué sur la méthode d’instance. La méthode n’a pas d’autres arguments. Il est appelé comme s’il s’agissait d’une méthode statique.
  • Les délégués sont créés pour la méthode M3 statique de type et de type CF; ils sont des délégués statiques ouverts.
  • Enfin, les délégués sont créés pour la méthode M4 statique de type et de type CF; chaque méthode a le type déclarant comme premier argument et une instance du type est fournie, de sorte que les délégués sont fermés sur leurs premiers arguments. La méthode M4 de type C affiche les ID propriétés de l’instance liée et de l’argument.
using System;
using System.Reflection;

// Declare a delegate type. The object of this code example
// is to show all the methods this delegate can bind to.
//
public delegate void D(C1 c);

// Declare two sample classes, C1 and F. Class C1 has an ID
// property so instances can be identified.
//
public class C1
{
    private int id;
    public int ID { get { return id; } }
    public C1(int id) { this.id = id; }

    public void M1(C1 c)
    {
        Console.WriteLine("Instance method M1(C1 c) on C1:  this.id = {0}, c.ID = {1}",
            this.id, c.ID);
    }

    public void M2()
    {
        Console.WriteLine("Instance method M2() on C1:  this.id = {0}",
            this.id);
    }

    public static void M3(C1 c)
    {
        Console.WriteLine("Static method M3(C1 c) on C1:  c.ID = {0}", c.ID);
    }

    public static void M4(C1 c1, C1 c2)
    {
        Console.WriteLine("Static method M4(C1 c1, C1 c2) on C1:  c1.ID = {0}, c2.ID = {1}",
            c1.ID, c2.ID);
    }
}

public class F
{
    public void M1(C1 c)
    {
        Console.WriteLine("Instance method M1(C1 c) on F:  c.ID = {0}",
            c.ID);
    }

    public static void M3(C1 c)
    {
        Console.WriteLine("Static method M3(C1 c) on F:  c.ID = {0}", c.ID);
    }

    public static void M4(F f, C1 c)
    {
        Console.WriteLine("Static method M4(F f, C1 c) on F:  c.ID = {0}",
            c.ID);
    }
}

public class Example
{
    public static void Main()
    {
        C1 c1 = new C1(42);
        C1 c2 = new C1(1491);
        F f1 = new F();

        D d;

        // Instance method with one argument of type C1.
        MethodInfo cmi1 = typeof(C1).GetMethod("M1");
        // Instance method with no arguments.
        MethodInfo cmi2 = typeof(C1).GetMethod("M2");
        // Static method with one argument of type C1.
        MethodInfo cmi3 = typeof(C1).GetMethod("M3");
        // Static method with two arguments of type C1.
        MethodInfo cmi4 = typeof(C1).GetMethod("M4");

        // Instance method with one argument of type C1.
        MethodInfo fmi1 = typeof(F).GetMethod("M1");
        // Static method with one argument of type C1.
        MethodInfo fmi3 = typeof(F).GetMethod("M3");
        // Static method with an argument of type F and an argument
        // of type C1.
        MethodInfo fmi4 = typeof(F).GetMethod("M4");

        Console.WriteLine("\nAn instance method on any type, with an argument of type C1.");
        // D can represent any instance method that exactly matches its
        // signature. Methods on C1 and F are shown here.
        //
        d = (D)Delegate.CreateDelegate(typeof(D), c1, cmi1);
        d(c2);
        d = (D)Delegate.CreateDelegate(typeof(D), f1, fmi1);
        d(c2);

        Console.WriteLine("\nAn instance method on C1 with no arguments.");
        // D can represent an instance method on C1 that has no arguments;
        // in this case, the argument of D represents the hidden first
        // argument of any instance method. The delegate acts like a
        // static method, and an instance of C1 must be passed each time
        // it is invoked.
        //
        d = (D)Delegate.CreateDelegate(typeof(D), null, cmi2);
        d(c1);

        Console.WriteLine("\nA static method on any type, with an argument of type C1.");
        // D can represent any static method with the same signature.
        // Methods on F and C1 are shown here.
        //
        d = (D)Delegate.CreateDelegate(typeof(D), null, cmi3);
        d(c1);
        d = (D)Delegate.CreateDelegate(typeof(D), null, fmi3);
        d(c1);

        Console.WriteLine("\nA static method on any type, with an argument of");
        Console.WriteLine("    that type and an argument of type C1.");
        // D can represent any static method with one argument of the
        // type the method belongs and a second argument of type C1.
        // In this case, the method is closed over the instance of
        // supplied for the its first argument, and acts like an instance
        // method. Methods on F and C1 are shown here.
        //
        d = (D)Delegate.CreateDelegate(typeof(D), c1, cmi4);
        d(c2);
        Delegate test =
            Delegate.CreateDelegate(typeof(D), f1, fmi4, false);

        // This final example specifies false for throwOnBindFailure
        // in the call to CreateDelegate, so the variable 'test'
        // contains Nothing if the method fails to bind (for
        // example, if fmi4 happened to represent a method of
        // some class other than F).
        //
        if (test != null)
        {
            d = (D)test;
            d(c2);
        }
    }
}

/* This code example produces the following output:

An instance method on any type, with an argument of type C1.
Instance method M1(C1 c) on C1:  this.id = 42, c.ID = 1491
Instance method M1(C1 c) on F:  c.ID = 1491

An instance method on C1 with no arguments.
Instance method M2() on C1:  this.id = 42

A static method on any type, with an argument of type C1.
Static method M3(C1 c) on C1:  c.ID = 42
Static method M3(C1 c) on F:  c.ID = 42

A static method on any type, with an argument of
    that type and an argument of type C1.
Static method M4(C1 c1, C1 c2) on C1:  c1.ID = 42, c2.ID = 1491
Static method M4(F f, C1 c) on F:  c.ID = 1491
*/
open System

// Declare two sample classes, C and F. Class C has an ID
// property so instances can be identified.
type C(id) =
    member _.ID = id 

    member _.M1(c: C) =
        printfn $"Instance method M1(C c) on C:  this.id = {id}, c.ID = {c.ID}"

    member _.M2() =
        printfn $"Instance method M2() on C:  this.id = {id}"

    static member M3(c: C) =
        printfn $"Static method M3(C c) on C:  c.ID = {c.ID}"

    static member M4(c1: C, c2: C) =
        printfn $"Static method M4(C c1, C c2) on C:  c1.ID = {c1.ID}, c2.ID = {c2.ID}"

// Declare a delegate type. The object of this code example
// is to show all the methods this delegate can bind to.
type D = delegate of C -> unit


type F() =
    member _.M1(c: C) =
        printfn $"Instance method M1(C c) on F:  c.ID = {c.ID}"

    member _.M3(c: C) =
        printfn $"Static method M3(C c) on F:  c.ID = {c.ID}"

    member _.M4(f: F, c: C) =
        printfn $"Static method M4(F f, C c) on F:  c.ID = {c.ID}"

[<EntryPoint>]
let main _ =
    let c1 = C 42
    let c2 = C 1491
    let f1 = F()

    // Instance method with one argument of type C.
    let cmi1 = typeof<C>.GetMethod "M1"
    // Instance method with no arguments.
    let cmi2 = typeof<C>.GetMethod "M2"
    // Static method with one argument of type C.
    let cmi3 = typeof<C>.GetMethod "M3"
    // Static method with two arguments of type C.
    let cmi4 = typeof<C>.GetMethod "M4"

    // Instance method with one argument of type C.
    let fmi1 = typeof<F>.GetMethod "M1"
    // Static method with one argument of type C.
    let fmi3 = typeof<F>.GetMethod "M3"
    // Static method with an argument of type F and an argument
    // of type C.
    let fmi4 = typeof<F>.GetMethod "M4"

    printfn "\nAn instance method on any type, with an argument of type C."
    // D can represent any instance method that exactly matches its
    // signature. Methods on C and F are shown here.
    let d = Delegate.CreateDelegate(typeof<D>, c1, cmi1) :?> D
    d.Invoke c2
    let d =  Delegate.CreateDelegate(typeof<D>, f1, fmi1) :?> D
    d.Invoke c2

    Console.WriteLine("\nAn instance method on C with no arguments.")
    // D can represent an instance method on C that has no arguments
    // in this case, the argument of D represents the hidden first
    // argument of any instance method. The delegate acts like a
    // static method, and an instance of C must be passed each time
    // it is invoked.
    let d = Delegate.CreateDelegate(typeof<D>, null, cmi2) :?> D
    d.Invoke c1

    printfn "\nA static method on any type, with an argument of type C."
    // D can represent any static method with the same signature.
    // Methods on F and C are shown here.
    let d = Delegate.CreateDelegate(typeof<D>, null, cmi3) :?> D
    d.Invoke c1
    let d = Delegate.CreateDelegate(typeof<D>, null, fmi3) :?> D
    d.Invoke c1

    printfn "\nA static method on any type, with an argument of"
    printfn "    that type and an argument of type C."
    // D can represent any static method with one argument of the
    // type the method belongs and a second argument of type C.
    // In this case, the method is closed over the instance of
    // supplied for the its first argument, and acts like an instance
    // method. Methods on F and C are shown here.
    let d = Delegate.CreateDelegate(typeof<D>, c1, cmi4) :?> D
    d.Invoke c2
    let test =
        Delegate.CreateDelegate(typeof<D>, f1, fmi4, false)

    // This final example specifies false for throwOnBindFailure
    // in the call to CreateDelegate, so the variable 'test'
    // contains Nothing if the method fails to bind (for
    // example, if fmi4 happened to represent a method of
    // some class other than F).
    match test with
    | :? D as d ->
        d.Invoke c2
    | _ -> ()
    0

// This code example produces the following output:
//     An instance method on any type, with an argument of type C.
//     Instance method M1(C c) on C:  this.id = 42, c.ID = 1491
//     Instance method M1(C c) on F:  c.ID = 1491
//    
//     An instance method on C with no arguments.
//     Instance method M2() on C:  this.id = 42
//    
//     A static method on any type, with an argument of type C.
//     Static method M3(C c) on C:  c.ID = 42
//     Static method M3(C c) on F:  c.ID = 42
//    
//     A static method on any type, with an argument of
//         that type and an argument of type C.
//     Static method M4(C c1, C c2) on C:  c1.ID = 42, c2.ID = 1491
//     Static method M4(F f, C c) on F:  c.ID = 1491
Imports System.Reflection
Imports System.Security.Permissions

' Declare a delegate type. The object of this code example
' is to show all the methods this delegate can bind to.
'
Public Delegate Sub D(ByVal c As C) 

' Declare two sample classes, C and F. Class C has an ID
' property so instances can be identified.
'
Public Class C

    Private _id As Integer

    Public ReadOnly Property ID() As Integer 
        Get
            Return _id
        End Get
    End Property

    Public Sub New(ByVal newId As Integer) 
        Me._id = newId
    End Sub
    
    Public Sub M1(ByVal c As C) 
        Console.WriteLine("Instance method M1(c As C) on C:  this.id = {0}, c.ID = {1}", _
            Me.id, c.ID)
    End Sub
    
    Public Sub M2() 
        Console.WriteLine("Instance method M2() on C:  this.id = {0}", Me.id)
    End Sub
    
    Public Shared Sub M3(ByVal c As C) 
        Console.WriteLine("Shared method M3(c As C) on C:  c.ID = {0}", c.ID)
    End Sub
    
    Public Shared Sub M4(ByVal c1 As C, ByVal c2 As C) 
        Console.WriteLine("Shared method M4(c1 As C, c2 As C) on C:  c1.ID = {0}, c2.ID = {1}", _
            c1.ID, c2.ID)
    End Sub
End Class


Public Class F
    
    Public Sub M1(ByVal c As C) 
        Console.WriteLine("Instance method M1(c As C) on F:  c.ID = {0}", c.ID)
    End Sub
    
    Public Shared Sub M3(ByVal c As C) 
        Console.WriteLine("Shared method M3(c As C) on F:  c.ID = {0}", c.ID)
    End Sub
    
    Public Shared Sub M4(ByVal f As F, ByVal c As C) 
        Console.WriteLine("Shared method M4(f As F, c As C) on F:  c.ID = {0}", c.ID)
    End Sub
End Class

Public Class Example5

    Public Shared Sub Main()

        Dim c1 As New C(42)
        Dim c2 As New C(1491)
        Dim f1 As New F()

        Dim d As D

        ' Instance method with one argument of type C.
        Dim cmi1 As MethodInfo = GetType(C).GetMethod("M1")
        ' Instance method with no arguments.
        Dim cmi2 As MethodInfo = GetType(C).GetMethod("M2")
        ' Shared method with one argument of type C.
        Dim cmi3 As MethodInfo = GetType(C).GetMethod("M3")
        ' Shared method with two arguments of type C.
        Dim cmi4 As MethodInfo = GetType(C).GetMethod("M4")

        ' Instance method with one argument of type C.
        Dim fmi1 As MethodInfo = GetType(F).GetMethod("M1")
        ' Shared method with one argument of type C.
        Dim fmi3 As MethodInfo = GetType(F).GetMethod("M3")
        ' Shared method with an argument of type F and an 
        ' argument of type C.
        Dim fmi4 As MethodInfo = GetType(F).GetMethod("M4")

        Console.WriteLine(vbLf & "An instance method on any type, with an argument of type C.")
        ' D can represent any instance method that exactly matches its
        ' signature. Methods on C and F are shown here.
        '
        d = CType([Delegate].CreateDelegate(GetType(D), c1, cmi1), D)
        d(c2)
        d = CType([Delegate].CreateDelegate(GetType(D), f1, fmi1), D)
        d(c2)

        Console.WriteLine(vbLf & "An instance method on C with no arguments.")
        ' D can represent an instance method on C that has no arguments;
        ' in this case, the argument of D represents the hidden first
        ' argument of any instance method. The delegate acts like a 
        ' Shared method, and an instance of C must be passed each time
        ' it is invoked.
        '
        d = CType([Delegate].CreateDelegate(GetType(D), Nothing, cmi2), D)
        d(c1)

        Console.WriteLine(vbLf & "A Shared method on any type, with an argument of type C.")
        ' D can represent any Shared method with the same signature.
        ' Methods on F and C are shown here.
        '
        d = CType([Delegate].CreateDelegate(GetType(D), Nothing, cmi3), D)
        d(c1)
        d = CType([Delegate].CreateDelegate(GetType(D), Nothing, fmi3), D)
        d(c1)

        Console.WriteLine(vbLf & "A Shared method on any type, with an argument of")
        Console.WriteLine("    that type and an argument of type C.")
        ' D can represent any Shared method with one argument of the
        ' type the method belongs and a second argument of type C.
        ' In this case, the method is closed over the instance of
        ' supplied for the its first argument, and acts like an instance
        ' method. Methods on F and C are shown here.
        '
        d = CType([Delegate].CreateDelegate(GetType(D), c1, cmi4), D)
        d(c2)
        Dim test As [Delegate] =
            [Delegate].CreateDelegate(GetType(D), f1, fmi4, False)

        ' This final example specifies False for throwOnBindFailure 
        ' in the call to CreateDelegate, so the variable 'test'
        ' contains Nothing if the method fails to bind (for 
        ' example, if fmi4 happened to represent a method of  
        ' some class other than F).
        '
        If test IsNot Nothing Then
            d = CType(test, D)
            d(c2)
        End If

    End Sub
End Class

' This code example produces the following output:
'
'An instance method on any type, with an argument of type C.
'Instance method M1(c As C) on C:  this.id = 42, c.ID = 1491
'Instance method M1(c As C) on F:  c.ID = 1491
'
'An instance method on C with no arguments.
'Instance method M2() on C:  this.id = 42
'
'A Shared method on any type, with an argument of type C.
'Shared method M3(c As C) on C:  c.ID = 42
'Shared method M3(c As C) on F:  c.ID = 42
'
'A Shared method on any type, with an argument of
'    that type and an argument of type C.
'Shared method M4(c1 As C, c2 As C) on C:  c1.ID = 42, c2.ID = 1491
'Shared method M4(f As F, c As C) on F:  c.ID = 1491
'

Types de paramètres compatibles et type de retour

Les types de paramètres et le type de retour d’un délégué créé à l’aide de cette surcharge de méthode doivent être compatibles avec les types de paramètres et le type de retour de la méthode que le délégué représente ; les types n’ont pas besoin de correspondre exactement.

Le paramètre d'un délégué est compatible avec le paramètre correspondant d'une méthode si le type de paramètre du délégué est plus restrictif que le type de paramètre de la méthode. En effet, cela garantit qu'un argument transmis au délégué peut être transmis à la méthode en toute sécurité.

De même, le type de retour d’un délégué est compatible avec le type de retour d’une méthode si le type de retour de la méthode est plus restrictif que le type de retour du délégué, car cela garantit que le cast de la valeur de retour de la méthode peut être effectué sans risque au type de retour du délégué.

Par exemple, un délégué avec un paramètre de type Hashtable et un type de Object retour peut représenter une méthode avec un paramètre de type Object et une valeur de retour de type Hashtable.

Déterminer les méthodes qu’un délégué peut représenter

Une autre façon utile de penser à la flexibilité fournie par la CreateDelegate(Type, Object, MethodInfo) surcharge est que n’importe quel délégué donné peut représenter quatre combinaisons différentes de la signature de méthode et du type de méthode (statique et instance). Considérez un type D délégué avec un argument de type C. Les méthodes D suivantes peuvent représenter, ignorant le type de retour, car il doit correspondre dans tous les cas :

  • D peut représenter n’importe quelle méthode d’instance qui a exactement un argument de type C, quel que soit le type auquel appartient la méthode d’instance. Lorsqu’elle CreateDelegate est appelée, firstArgument est une instance du type method appartient et le délégué résultant est dit fermé sur cette instance. (Trivially, D peut également être fermé sur une référence Null s’il firstArgument s’agit d’une référence null.)

  • D peut représenter une méthode d’instance de C ce qui n’a aucun argument. Quand CreateDelegate elle est appelée, firstArgument est une référence Null. Le délégué résultant représente une méthode d’instance ouverte et une instance de C doit être fournie chaque fois qu’elle est appelée.

  • D peut représenter une méthode statique qui accepte un argument de type C, et cette méthode peut appartenir à n’importe quel type. Quand CreateDelegate elle est appelée, firstArgument est une référence Null. Le délégué résultant représente une méthode statique ouverte et une instance de C doit être fournie chaque fois qu’elle est appelée.

  • D peut représenter une méthode statique qui appartient au type F et a deux arguments, de type et de type FC. Quand CreateDelegate elle est appelée, firstArgument est une instance de F. Le délégué résultant représente une méthode statique qui est fermée sur cette instance de F. Notez que dans le cas où F et C sont le même type, la méthode statique a deux arguments de ce type. (Dans ce cas, D est fermé sur une référence Null s’il firstArgument s’agit d’une référence null.)