Poznámka:
Přístup k této stránce vyžaduje autorizaci. Můžete se zkusit přihlásit nebo změnit adresáře.
Přístup k této stránce vyžaduje autorizaci. Můžete zkusit změnit adresáře.
Tento článek obsahuje doplňující poznámky k referenční dokumentaci pro toto rozhraní API.
Metody CreateDelegate vytvoří delegáta zadaného typu.
metoda CreateDelegate(Type, MethodInfo)
Toto přetížení metody je ekvivalentní zavolání metody CreateDelegate(Type, MethodInfo, Boolean) a určení true pro throwOnBindFailure.
Příklady
Tato část obsahuje dva příklady kódu. První příklad ukazuje dva druhy delegátů, které lze vytvořit s tímto přetížením metody: otevřít přes metodu instance a otevřít přes statickou metodu.
Druhý příklad kódu ukazuje kompatibilní typy parametrů a návratové typy.
Příklad 1
Následující příklad kódu demonstruje dva způsoby vytvoření delegáta pomocí tohoto přetížení metody CreateDelegate.
Poznámka:
Existují dvě přetížení CreateDelegate metody, která určují MethodInfo bez prvního argumentu; jejich funkcionalita je stejná s tím rozdílem, že jedno vám umožňuje určit, zda má být vyvolána výjimka při selhání vytvoření vazby, a druhé vždy výjimku vyvolá. Tento příklad kódu používá obě přetížení.
Příklad deklaruje třídu C se statickou metodou M2 a metodou instance M1, a dva typy delegátů: D1 přebírá instanci C a řetězec, a D2 přebírá řetězec.
Druhá třída s názvem Example obsahuje kód, který vytvoří delegáty.
- Pro metodu
D1instance je vytvořen delegát typuM1představující metodu otevřené instance . Při vyvolání delegáta musí být předána instance. - Delegát typu
D2představující otevřenou statickou metodu je vytvořen pro statickou metoduM2.
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 = {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!
'
Příklad 2
Následující příklad kódu ukazuje kompatibilitu typů parametrů a návratových typů.
Příklad kódu definuje základní třídu pojmenovanou Base a třídu, Derived která je odvozena od Base. Odvozená třída má metodu static (Shared v jazyce Visual Basic) pojmenovanou MyMethod s jedním parametrem typu Base a návratovým typem Derived. Příklad kódu také definuje delegát s názvem Example , který má jeden parametr typu Derived a návratový Basetyp .
Příklad kódu ukazuje, že delegát pojmenovaný Example lze použít k reprezentaci metody MyMethod. Metoda může být vázána na delegáta, protože:
- Typ parametru delegáta (
Derived) je více omezující než typ parametruMyMethod(Base), takže je vždy bezpečné předat argument delegátaMyMethod. - Návratový
MyMethodtyp (Derived) je více omezující než typ parametru delegáta (Base), takže je vždy bezpečné přetypovat návratový typ metody na návratový typ delegáta.
Příklad kódu nevygeneruje žádný výstup.
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
metody CreateDelegate(Type, Object, MethodInfo) a CreateDelegate(Type, Object, MethodInfo, Boolean)
Funkcionalita těchto dvou přetížení je stejná, až na to, že jedno umožňuje určit, zda se má při selhání vazby vyvolat výjimka, zatímco druhé ji vždy vyvolá.
Typ delegáta a metoda musí mít kompatibilní návratové typy. To znamená, že návratový typ method musí být přiřaditelný k návratovému typu type.
firstArgument, druhý parametr těchto přetížení, je prvním argumentem metody, kterou delegát představuje. Je-li firstArgument zadán, je při každém vyvolání delegáta předán do method; říká se, že firstArgument je svázán s delegátem, a delegát se označuje, že je uzavřen nad svým prvním argumentem. Pokud method je static (Shared v jazyce Visual Basic), seznam argumentů zadaný při vyvolání delegáta obsahuje všechny parametry kromě první; pokud method je metoda instance, pak firstArgument se předá skrytému parametru instance (reprezentované this v jazyce C# nebo Me v jazyce Visual Basic).
Pokud je firstArgument zadán, musí být první parametr method referenční typ a firstArgument musí být kompatibilní s tímto typem.
Důležité
Pokud method je static (Sharedv jazyce Visual Basic) a jeho prvním parametrem je typObject, ValueTypefirstArgument může být typ hodnoty. V tomto případě je firstArgument automaticky zapouzdřeno. K automatickému boxování nedochází u žádných dalších argumentů, jako by tomu bylo při volání funkce v jazycích C# nebo Visual Basic.
Pokud firstArgument je nulový odkaz a method je metoda instance, výsledek závisí na podpisech typu delegáta type a method.
- Pokud podpis
typeexplicitně obsahuje skrytý první parametrmethod, delegát se říká, že představuje metodu otevřené instance. Při vyvolání delegáta se první argument v seznamu argumentů předá skrytému parametrumethodinstance . - Pokud se podpisy
methodatypeshodují (to znamená, že všechny typy parametrů jsou kompatibilní), pak se říká, že delegát je uzamčen na nulovou referenci. Vyvolání delegáta se podobá volání metody instance na instanci null, což není zvlášť užitečná věc, kterou je třeba udělat.
Pokud firstArgument je nulový odkaz a method je statický, výsledek závisí na signaturách typu delegáta type a method.
- Pokud se podpisy
methodatypeshodují (to znamená, že všechny typy parametrů jsou kompatibilní), říká se, že delegát představuje otevřenou statickou metodu. Toto je nejběžnější případ statických metod. V tomto případě můžete dosáhnout mírně lepšího výkonu pomocí metody CreateDelegate(Type, MethodInfo) tím, že ji přetížíte. - Pokud podpis
typezačíná druhým parametremmethoda zbývající typy parametrů jsou kompatibilní, znamená to, že delegát je uzavřen s ohledem na nulový odkaz. Při vyvolání delegáta se předá odkaz null prvnímu parametrumethod.
Příklad
Následující příklad kódu ukazuje všechny metody, které může jeden typ delegáta zastupovat: uzavřený přes metodu instance, otevřený přes metodu instance, otevřený přes statickou metodu a uzavřený přes statickou metodu.
Příklad kódu definuje dvě třídy C a Fa delegát typ D s jedním argumentem typu C. Třídy mají odpovídající statické a instance metody M1, M3 a M4, a třída C má také metodu instance M2, která nemá žádné argumenty.
Třetí třída s názvem Example obsahuje kód, který vytvoří delegáty.
- Delegáti jsou vytvořeni pro metodu
M1instancí typuCa pro metodu typuF; každý je svázán s instancí příslušného typu. MetodaM1typuCzobrazujeIDvlastnosti vázané instance a argumentu. - Delegát je vytvořen pro metodu
M2typuC. Jedná se o delegáta otevřené instance, ve kterém argument delegát představuje skrytý první argument metody instance. Metoda nemá žádné další argumenty. Volá se, jako by šlo o statickou metodu. - Delegáti se vytvářejí pro statickou metodu
M3typuCa typuF. Jedná se o otevřené statické delegáty. - Nakonec se delegáti vytvoří pro statickou metodu
M4typuCaF; každá metoda má jako první argument svůj deklarovaný typ a je poskytnuta instance typu, takže delegáti jsou uzavřeni nad těmito prvními argumenty. MetodaM4typuCzobrazujeIDvlastnosti vázané instance a argumentu.
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 = {this.id}");
}
public static void M3(C1 c)
{
Console.WriteLine($"Static method M3(C1 c) on C1: c.ID = {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 = {c.ID}");
}
public static void M3(C1 c)
{
Console.WriteLine($"Static method M3(C1 c) on F: c.ID = {c.ID}");
}
public static void M4(F f, C1 c)
{
Console.WriteLine($"Static method M4(F f, C1 c) on F: c.ID = {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
'
Kompatibilní typy parametrů a návratový typ
Typy parametrů a návratový typ delegáta vytvořeného pomocí tohoto přetížení metody musí být kompatibilní s typy parametrů a návratovým typem metody, kterou delegát představuje; typy se nemusí přesně shodovat.
Parametr delegáta je kompatibilní s odpovídajícím parametrem metody, pokud je typ parametru delegáta více omezující než typ parametru metody, protože to zaručuje, že argument předaný delegátu lze metodě bezpečně předat.
Podobně návratový typ delegáta je kompatibilní s návratovým typem metody, pokud je návratový typ metody více omezující než návratový typ delegáta, protože to zaručuje, že návratovou hodnotu metody lze bezpečně přetypovat na návratový typ delegáta.
Například delegát s parametrem typu Hashtable a návratovým typem Object může představovat metodu s parametrem typu Object a návratovou hodnotou typu Hashtable.
Určení metod, které delegát může představovat
Dalším užitečným způsobem, jak si představit flexibilitu poskytovanou přetížením CreateDelegate(Type, Object, MethodInfo) , je, že každý daný delegát může představovat čtyři různé kombinace signatury metody a druhu metody (statické versus instance). Zvažte typ D delegáta s jedním argumentem typu C. Následující popisuje metody, které může D představovat, přičemž ignoruje návratový typ, protože musí být shodný ve všech případech.
Dmůže představovat jakoukoli metodu instance, která má přesně jeden argument typuC, bez ohledu na typ, ke kterému metoda instance patří. Když je CreateDelegate volána,firstArgumentje instancí typu, ke kterémumethodpatří, a výsledný delegát je považován za uzavřený nad touto instancí. (Triviálně lze také uzavřít nad nulovým odkazem, pokud jeDnulový odkazfirstArgument.)Dmůže představovat metoduCinstance, která nemá žádné argumenty. Když je zavolán CreateDelegate,firstArgumentje nulová reference. Výsledný delegát představuje metodu otevřené instance a při každém vyvolání musí být zadána instanceC.Dmůže představovat statickou metodu, která přebírá jeden argument typuCa tato metoda může patřit do libovolného typu. Když je zavolán CreateDelegate,firstArgumentje nulová reference. Výsledný delegát představuje otevřenou statickou metodu a při každém vyvolání musí být zadána instanceC.Dmůže představovat statickou metodu, která patří k typuFa má dva argumenty, typuFa typuC. Když je CreateDelegate použito,firstArgumentje instanceF. Výsledný delegát představuje statickou metodu, která je uzavřena nad danou instancíF. Všimněte si, že v případěF, kdy aCjsou stejného typu, má statická metoda dva argumenty tohoto typu. (V tomto případě, pokudDje odkaz null, je uzavřena nad odkazem nullfirstArgument.)