« Delegate » : différence entre les versions

De Banane Atomic
Aller à la navigationAller à la recherche
 
Ligne 78 : Ligne 78 :
* [https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/expression-trees doc microsoft]
* [https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/expression-trees doc microsoft]
* [[Réflexion#Expression_Tree_.C3.A0_la_place_de_la_r.C3.A9flexion | Expression Tree à la place de la réflexion]]
* [[Réflexion#Expression_Tree_.C3.A0_la_place_de_la_r.C3.A9flexion | Expression Tree à la place de la réflexion]]
* [https://tyrrrz.me/blog/expression-trees Working with Expression Trees in C#]


<kode lang='cs'>
<kode lang='cs'>

Dernière version du 14 mars 2021 à 16:51

Definition

Un délégué est un pointeur sur méthode.

delegate

Csharp.svg
// Définition du délégué correspondant à la signature de la méthode CountLetters
delegate int MonDélégué(string inString);

int CountLetters(string inString)
{
    return inString.Length;
}

// Différente manière d'instancier le délégué
MonDélégué monDéléguéA = new MonDélégué(CountLetters);  // named function
// écriture simplifiée
MonDélégué monDéléguéA = CountLetters;
// anonymous function (C# 2)
MonDélégué monDéléguéA = delegate(string inString) { return inString.Length; };
// lambda expression (C# 3)
MonDélégué monDéléguéA = (string inString) => { return inString.Length; };
// écriture simplifiée
MonDélégué monDéléguéA = inString => inString.Length;

// appel du délégué
monDéléguéA("1");

Func

Signature de délégué générique ayant de 0 à 16 arguments d'entrée et 1 argument de sortie.
Cette signature de délégué générique existe grâce à la covariance (out) et la contra variance (in) des génériques introduit avec C# 4.

Csharp.svg
// Signatures déjà existantes, à ne pas recopier dans le code
public delegate TResult Func<out TResult>();

public delegate TResult Func<in T1, in T2, in T3, in T4, in T5, in T6, in T7, in T8, in T9, 
    in T10, in T11, in T12, in T13, in T14, in T15, in T16, out TResult>
    (T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, 
        T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14, T15 arg15, T16 arg16);
Csharp.svg
Func<string, int> monDéléguéA = CountLetters;
monDéléguéA("1");

Func<string, int> monDéléguéB = delegate(string inString)
    {
        return inString.Length;
    };
monDéléguéB("12");

Func<string, int> monDéléguéC = inString => inString.Length;
monDéléguéC("123");

Action

Signature de délégué générique ayant de 1 à 16 arguments d'entrée et 0 argument de sortie.

Csharp.svg
// Signature déjà existante, à ne pas recopier dans le code
public delegate void Action<in T>(T obj);

// utilisation
Action<string> a = inString => Console.WriteLine(inString);
a("Ok");

Predicate

Signature de délégué générique ayant de 1 argument d'entrée et 1 argument de sortie.

Csharp.svg
public delegate bool Predicate<in T>(T obj);

Expression Tree

An expression is a sequence of operands and operators that can be evaluated to a single value.
Expression trees represent code as a tree-like data structure, where each node is an expression.

Cs.svg
Expression<Func<int, int>> multiplyByFiveExpression = num => num * 5;

// compiler une expression donne un delegate
Func<int, int> multiplyByFiveFunction = multiplyByFiveExpression.Compile();

// appel
multiplyByFiveFunction(10);  // 50

Console.WriteLine(multiplyByFiveExpression);                   // num => (num * 5)
Console.WriteLine(multiplyByFiveExpression.Body);              // (num * 5)
Console.WriteLine(multiplyByFiveExpression.Parameters.Count);  // 1
Console.WriteLine(multiplyByFiveExpression.Parameters[0]);     // num

Multicasting et gestion des exceptions

Si une des méthodes associées à l'event lance une exception, les méethodes associées suivantes ne seront pas exécutées.

Cs.svg
delegate void MyDelegate();

MyDelegate a = () => Console.WriteLine("1");
a += () =>
{
    Console.WriteLine("2");
    throw new Exception("xxx");
};
a += () => Console.WriteLine("3");

var exceptions = new List<Exception>();
// exécute toutes les méthodes et capture les exceptions
foreach (Delegate handler in a.GetInvocationList())
{
    try
    {
        handler.DynamicInvoke();
    }
    catch (Exception ex)
    {
        exceptions.Add(ex);
    }
}
// relance les exceptions
if (exceptions.Any())
{
    throw new AggregateException(exceptions);
}