Critères spéciauxPattern Matching

Les modèles vérifient qu’une valeur a une certaine forme et peuvent extraire des informations de la valeur quand celle-ci a la forme correspondante.Patterns test that a value has a certain shape, and can extract information from the value when it has the matching shape. Les critères spéciaux offrent une syntaxe plus concise pour les algorithmes que vous utilisez déjà aujourd’hui.Pattern matching provides more concise syntax for algorithms you already use today. Vous pouvez déjà créer des algorithmes de critères spéciaux à l’aide de la syntaxe existante.You already create pattern matching algorithms using existing syntax. Pour cela, vous écrivez des instructions if ou switch qui testent une valeur.You write if or switch statements that test values. Ensuite, quand ces instructions correspondent, vous extrayez et utilisez les informations de cette valeur.Then, when those statements match, you extract and use information from that value. Les nouveaux éléments de syntaxe étendent les instructions que vous connaissez déjà : is et switch.The new syntax elements are extensions to statements you're already familiar with: is and switch. Ces nouvelles extensions permettent à la fois de tester une valeur et d’extraire les informations de cette valeur.These new extensions combine testing a value and extracting that information.

Dans cet article, nous allons examiner la nouvelle syntaxe pour voir en quoi elle rend le code plus lisible et plus concis.In this article, we'll look at the new syntax to show you how it enables readable, concise code. Les critères spéciaux permettent d’utiliser des idiomes dans lesquels le code et les données sont séparés, contrairement aux conceptions orientées objet où les données et les méthodes qui les manipulent sont étroitement couplées.Pattern matching enables idioms where data and the code are separated, unlike object-oriented designs where data and the methods that manipulate them are tightly coupled.

Pour illustrer ces nouveaux idiomes, nous allons manipuler des structures représentant des formes géométriques à l’aide d’instructions de critères spéciaux.To illustrate these new idioms, let's work with structures that represent geometric shapes using pattern matching statements. Vous savez probablement déjà concevoir des hiérarchies de classes et créer des méthodes virtuelles et méthodes substituées pour personnaliser le comportement d’un objet en fonction de son type à l’exécution.You're probably familiar with building class hierarchies and creating virtual methods and overridden methods to customize object behavior based on the runtime type of the object.

Ces techniques ne sont pas possibles avec des données qui ne sont pas structurées dans une hiérarchie de classes.Those techniques aren't possible for data that isn't structured in a class hierarchy. Quand les données et les méthodes sont séparées, vous avez besoin d’autres outils.When data and methods are separate, you need other tools. Les nouvelles constructions de critères spéciaux utilisent une syntaxe simplifiée pour examiner les données et manipuler le flux de contrôle en fonction de la condition de ces données.The new pattern matching constructs enable cleaner syntax to examine data and manipulate control flow based on any condition of that data. Vous écrivez déjà des instructions if et switch qui testent la valeur d’une variable.You already write if statements and switch that test a variable's value. Vous écrivez déjà des instructions is qui testent le type d’une variable.You write is statements that test a variable's type. Les critères spéciaux ajoutent de nouvelles fonctionnalités à ces instructions.Pattern matching adds new capabilities to those statements.

Dans cet article, vous allez créer une méthode qui calcule la surface de différentes formes géométriques.In this article, you'll build a method that computes the area of different geometric shapes. Pour cela, vous n’allez pas utiliser de techniques orientées objet, ni créer une hiérarchie de classes pour les différentes formes.But, you'll do it without resorting to object-oriented techniques and building a class hierarchy for the different shapes. Vous allez utiliser des critères spéciaux à la place.You'll use pattern matching instead. Tout au long de cet exemple, comparez ce code avec le même code structuré comme une hiérarchie d’objets.As you go through this sample, contrast this code with how it would be structured as an object hierarchy. Quand les données à interroger et à manipuler ne constituent pas une hiérarchie de classes, les critères spéciaux permettent de réaliser des conceptions élégantes.When the data you must query and manipulate isn't a class hierarchy, pattern matching enables elegant designs.

Au lieu de commencer avec une définition de forme abstraite et d’ajouter ensuite différentes classes de formes spécifiques, écrivez d’abord les définitions de données simples pour chacune des formes géométriques :Rather than starting with an abstract shape definition and adding different specific shape classes, let's start instead with simple data only definitions for each of the geometric shapes:

public class Square
{
    public double Side { get; }

    public Square(double side)
    {
        Side = side;
    }
}
public class Circle
{
    public double Radius { get; }

    public Circle(double radius)
    {
        Radius = radius;
    }
}
public struct Rectangle
{
    public double Length { get; }
    public double Height { get; }

    public Rectangle(double length, double height)
    {
        Length = length;
        Height = height;
    }
}
public class Triangle
{
    public double Base { get; }
    public double Height { get; }

    public Triangle(double @base, double height)
    {
        Base = @base;
        Height = height;
    }
}

À partir de ces structures, écrivez une méthode qui calcule la surface d’une forme.From these structures, let's write a method that computes the area of some shape.

Expression du modèle de type isThe is type pattern expression

Avant C# 7.0, vous deviez tester chaque type dans une série d’instructions if et is :Before C# 7.0, you'd need to test each type in a series of if and is statements:

public static double ComputeArea(object shape)
{
    if (shape is Square)
    {
        var s = (Square)shape;
        return s.Side * s.Side;
    } 
    else if (shape is Circle)
    {
        var c = (Circle)shape;
        return c.Radius * c.Radius * Math.PI;
    }
    // elided
    throw new ArgumentException(
        message: "shape is not a recognized shape",
        paramName: nameof(shape));
}

Le code ci-dessus est une expression standard du modèle de type : vous testez une variable pour déterminer son type et vous effectuez une action différente en fonction de ce type.That code above is a classic expression of the type pattern: You're testing a variable to determine its type and taking a different action based on that type.

Vous pouvez simplifier ce code en ajoutant des extensions à l’expression is pour assigner une variable si le test réussit :This code becomes simpler using extensions to the is expression to assign a variable if the test succeeds:

public static double ComputeAreaModernIs(object shape)
{
    if (shape is Square s)
        return s.Side * s.Side;
    else if (shape is Circle c)
        return c.Radius * c.Radius * Math.PI;
    else if (shape is Rectangle r)
        return r.Height * r.Length;
    // elided
    throw new ArgumentException(
        message: "shape is not a recognized shape",
        paramName: nameof(shape));
}

Dans cette version mise à jour, l’expression is teste la variable et l’assigne à une nouvelle variable du type approprié.In this updated version, the is expression both tests the variable and assigns it to a new variable of the proper type. Remarquez également que cette version inclut le type Rectangle, qui est un struct.Also, notice that this version includes the Rectangle type, which is a struct. La nouvelle expression is peut être utilisée avec des types valeur et des types référence.The new is expression works with value types as well as reference types.

Les règles de langage des expressions de critères spéciaux vous aident à éviter une utilisation incorrecte des résultats d’une expression de correspondance.Language rules for pattern matching expressions help you avoid misusing the results of a match expression. Dans l’exemple ci-dessus, les variables s, c et r sont uniquement dans la portée et assignées de manière définitive quand les expressions de critères spéciaux respectives retournent le résultat true.In the example above, the variables s, c, and r are only in scope and definitely assigned when the respective pattern match expressions have true results. Si vous essayez d’utiliser l’une de ces variables à un autre emplacement, votre code génère des erreurs de compilateur.If you try to use either variable in another location, your code generates compiler errors.

Examinons ces deux règles en détail, en commençant par la portée.Let's examine both of those rules in detail, beginning with scope. La variable c est dans la portée uniquement dans la branche else de la première instruction if.The variable c is in scope only in the else branch of the first if statement. La variable s est dans la portée dans la méthode ComputeAreaModernIs.The variable s is in scope in the method ComputeAreaModernIs. Cela est dû au fait que chaque branche d’une instruction if établit une portée distincte pour les variables,That's because each branch of an if statement establishes a separate scope for variables. ce que ne fait pas l’instruction if proprement dite.However, the if statement itself doesn't. Cela signifie que les variables déclarées dans l’instruction if se trouvent dans la même portée que l’instruction if (dans ce cas, la méthode). Ce comportement n’est pas spécifique aux critères spéciaux, mais il s’agit du comportement défini pour les étendues de variables et les instructions if et else.That means variables declared in the if statement are in the same scope as the if statement (the method in this case.) This behavior isn't specific to pattern matching, but is the defined behavior for variable scopes and if and else statements.

Les variables c et s sont assignées quand les instructions if respectives ont la valeur true, selon la règle d’assignation définitive quand le résultat est true.The variables c and s are assigned when the respective if statements are true because of the definitely assigned when true mechanism.

Conseil

Les exemples de cette rubrique utilisent la construction recommandée où une expression de critères spéciaux is assigne de manière définitive la variable de correspondance dans la branche true de l’instruction if.The samples in this topic use the recommended construct where a pattern match is expression definitely assigns the match variable in the true branch of the if statement. Vous pourriez inverser la logique en écrivant if (!(shape is Square s)). La variable s serait alors assignée de manière définitive uniquement dans la branche false.You could reverse the logic by saying if (!(shape is Square s)) and the variable s would be definitely assigned only in the false branch. Cette pratique est possible dans C#, mais elle est déconseillée, car elle repose sur une logique plus compliquée à suivre.While this is valid C#, it is not recommended because it is more confusing to follow the logic.

Ces règles limitent le risque d’accéder accidentellement au résultat d’une expression de critères spéciaux dont le test n’a pas réussi.These rules mean that you're unlikely to accidentally access the result of a pattern match expression when that pattern wasn't met.

Utilisation des instructions de critères spéciaux switchUsing pattern matching switch statements

Au fil du temps, vous aurez peut-être besoin de prendre en charge d’autres types de formes.As time goes on, you may need to support other shape types. Si vous avez de plus en plus de conditions à tester, utiliser les expressions de critères spéciaux is peut devenir compliqué.As the number of conditions you're testing grows, you'll find that using the is pattern matching expressions can become cumbersome. En plus de nécessiter des instructions if pour chaque type à vérifier, les expressions is permettent uniquement de vérifier si l’entrée correspond à un type unique.In addition to requiring if statements on each type you want to check, the is expressions are limited to testing if the input matches a single type. Dans ce cas, les expressions de critères spéciaux switch sont plus adaptées.In this case, you'll find that the switch pattern matching expressions becomes a better choice.

L’instruction switch standard était une expression de modèle, qui prenait en charge le modèle de constante.The traditional switch statement was a pattern expression: it supported the constant pattern. Vous pouviez comparer une variable à n’importe quelle constante utilisée dans une instruction case :You could compare a variable to any constant used in a case statement:

public static string GenerateMessage(params string[] parts)
{
    switch (parts.Length)
    {
        case 0:
            return "No elements to the input";
        case 1:
            return $"One element: {parts[0]}";
        case 2:
            return $"Two elements: {parts[0]}, {parts[1]}";
        default:
            return $"Many elements. Too many to write";
    }
}

Le seul modèle pris en charge par l’instruction switch était le modèle de constante.The only pattern supported by the switch statement was the constant pattern. De plus, il était limité aux types numériques et au type string.It was further limited to numeric types and the string type. Ces restrictions ayant été supprimées, vous pouvez maintenant écrire une instruction switch en utilisant le modèle de type :Those restrictions have been removed, and you can now write a switch statement using the type pattern:

public static double ComputeAreaModernSwitch(object shape)
{
    switch (shape)
    {
        case Square s:
            return s.Side * s.Side;
        case Circle c:
            return c.Radius * c.Radius * Math.PI;
        case Rectangle r:
            return r.Height * r.Length;
        default:
            throw new ArgumentException(
                message: "shape is not a recognized shape",
                paramName: nameof(shape));
    }
}

L’instruction de critères spéciaux switch utilise une syntaxe qui est familière aux développeurs ayant utilisé l’instruction switch de style C standard.The pattern matching switch statement uses familiar syntax to developers who have used the traditional C-style switch statement. Chaque instruction case est évaluée, et le code en-dessous de la condition qui correspond à la variable d’entrée est exécuté.Each case is evaluated and the code beneath the condition that matches the input variable is executed. L’exécution du code ne continue pas d’une expression case à la suivante, car la syntaxe de l’instruction case impose que chaque case se termine par break, return ou goto.Code execution can't "fall through" from one case expression to the next; the syntax of the case statement requires that each case end with a break, return, or goto.

Notes

Les instructions goto pour accéder à une autre étiquette sont valides uniquement pour le modèle de constante (l’instruction switch standard).The goto statements to jump to another label are valid only for the constant pattern (the classic switch statement).

Il y a de nouvelles règles importantes qui régissent l’instruction switch.There are important new rules governing the switch statement. Les restrictions sur le type de la variable dans l’expression switch ont été supprimées.The restrictions on the type of the variable in the switch expression have been removed. Vous pouvez maintenant utiliser tous les types, comme le type object dans cet exemple.Any type, such as object in this example, may be used. Les expressions case ne sont plus limitées à des valeurs de constante.The case expressions are no longer limited to constant values. Avec la suppression de cette limitation, la réorganisation des sections switch peut changer le comportement d’un programme.Removing that limitation means that reordering switch sections may change a program's behavior.

Quand les expressions étaient limitées à des valeurs de constante, une seule étiquette case pouvait correspondre à la valeur de l’expression switch.When limited to constant values, no more than one case label could match the value of the switch expression. La conséquence de cette règle, associée à la règle selon laquelle une section switch ne devait pas passer à la section suivante, était que les sections switch pouvaient être réorganisées dans n’importe quel ordre sans que cela change le comportement du programme.Combine that with the rule that every switch section must not fall through to the next section, and it followed that the switch sections could be rearranged in any order without affecting behavior. Maintenant, avec les expressions switch généralisées, l’ordre de chaque section est important.Now, with more generalized switch expressions, the order of each section matters. Les expressions switch sont évaluées dans l’ordre textuel.The switch expressions are evaluated in textual order. L’exécution passe à la première étiquette switch qui correspond à l’expression switch.Execution transfers to the first switch label that matches the switch expression.
Le cas default n’est exécuté que si aucune autre étiquette case ne correspond.The default case will only be executed if no other case labels match. L’expression case default est évaluée en dernier, quel que soit son ordre textuel.The default case is evaluated last, regardless of its textual order. S’il n’existe aucun cas default ni aucune correspondance avec les autres instructions case, l’exécution passe à l’instruction suivant l’instruction switch.If there's no default case, and none of the other case statements match, execution continues at the statement following the switch statement. Aucun code d’étiquettes case n’est exécuté.None of the case labels code is executed.

Clauses when dans les expressions casewhen clauses in case expressions

Vous pouvez créer des expressions case spéciales pour les formes de surface 0 en ajoutant une clause when dans l’étiquette case.You can make special cases for those shapes that have 0 area by using a when clause on the case label. Un carré avec une longueur de côté de 0, ou un cercle de rayon 0, a une surface égale à 0.A square with a side length of 0, or a circle with a radius of 0 has a 0 area. Vous spécifiez cette condition en ajoutant une clause when dans l’étiquette case :You specify that condition using a when clause on the case label:

public static double ComputeArea_Version3(object shape)
{
    switch (shape)
    {
        case Square s when s.Side == 0:
        case Circle c when c.Radius == 0:
            return 0;

        case Square s:
            return s.Side * s.Side;
        case Circle c:
            return c.Radius * c.Radius * Math.PI;
        default:
            throw new ArgumentException(
                message: "shape is not a recognized shape",
                paramName: nameof(shape));
    }
}

Cette modification illustre quelques points importants relatifs à la nouvelle syntaxe.This change demonstrates a few important points about the new syntax. Tout d’abord, plusieurs étiquettes case peuvent être appliquées à une même section switch.First, multiple case labels can be applied to one switch section. Le bloc d’instructions est exécuté quand l’une de ces étiquettes est true.The statement block is executed when any of those labels is true. Dans ce cas, si l’expression switch est un cercle ou un carré de surface 0, la méthode retourne la constante 0.In this instance, if the switch expression is either a circle or a square with 0 area, the method returns the constant 0.

Cet exemple introduit deux variables différentes dans les deux étiquettes case du premier bloc switch.This example introduces two different variables in the two case labels for the first switch block. Notez que les instructions de ce bloc switch n’utilisent ni la variable c (pour le cercle), ni la variable s (pour le carré).Notice that the statements in this switch block don't use either the variables c (for the circle) or s (for the square). Aucune de ces variables n’est assignée de manière définitive dans ce bloc switch.Neither of those variables is definitely assigned in this switch block. Si l’une de ces étiquettes case correspond, cela signifie qu’une des variables a été assignée.If either of these cases match, clearly one of the variables has been assigned. Toutefois, il est impossible de déterminer laquelle a été assignée au moment de la compilation, car les deux cas peuvent correspondre à l’exécution.However, it's impossible to tell which has been assigned at compile time, because either case could match at runtime. C’est pourquoi, la plupart du temps, quand on utilise plusieurs étiquettes case dans le même bloc, on n’introduit pas de nouvelle variable dans l’instruction case ou on ne l’utilise que dans la clause when.For that reason, most times when you use multiple case labels for the same block, you won't introduce a new variable in the case statement, or you'll only use the variable in the when clause.

Après avoir ajouté ces formes de surface 0, ajoutez deux autres types de formes, un rectangle et un triangle :Having added those shapes with 0 area, let's add a couple more shape types: a rectangle and a triangle:

public static double ComputeArea_Version4(object shape)
{
    switch (shape)
    {
        case Square s when s.Side == 0:
        case Circle c when c.Radius == 0:
        case Triangle t when t.Base == 0 || t.Height == 0:
        case Rectangle r when r.Length == 0 || r.Height == 0:
            return 0;

        case Square s:
            return s.Side * s.Side;
        case Circle c:
            return c.Radius * c.Radius * Math.PI;
        case Triangle t:
            return t.Base * t.Height / 2;
        case Rectangle r:
            return r.Length * r.Height;
        default:
            throw new ArgumentException(
                message: "shape is not a recognized shape",
                paramName: nameof(shape));
    }
}

Avec cet ensemble de modifications, vous avez ajouté des étiquettes case pour l’expression case dégénérée, ainsi que des étiquettes et des blocs pour chacune des nouvelles formes.This set of changes adds case labels for the degenerate case, and labels and blocks for each of the new shapes.

Enfin, vous pouvez ajouter un cas null pour que l’argument ne soit pas null :Finally, you can add a null case to ensure the argument isn't null:

public static double ComputeArea_Version5(object shape)
{
    switch (shape)
    {
        case Square s when s.Side == 0:
        case Circle c when c.Radius == 0:
        case Triangle t when t.Base == 0 || t.Height == 0:
        case Rectangle r when r.Length == 0 || r.Height == 0:
            return 0;

        case Square s:
            return s.Side * s.Side;
        case Circle c:
            return c.Radius * c.Radius * Math.PI;
        case Triangle t:
            return t.Base * t.Height / 2;
        case Rectangle r:
            return r.Length * r.Height;
        case null:
            throw new ArgumentNullException(paramName: nameof(shape), message: "Shape must not be null");
        default:
            throw new ArgumentException(
                message: "shape is not a recognized shape",
                paramName: nameof(shape));
    }
}

Le comportement spécial du modèle null est intéressant, car sa constante null n’a pas de type, mais peut être convertie en un type référence ou un type Nullable.The special behavior for the null pattern is interesting because the constant null in the pattern doesn't have a type but can be converted to any reference type or nullable type. Plutôt que de convertir une valeur null en un type quelconque, le langage définit qu’une valeur null ne correspond à aucun modèle de type, quel que soit le type de la variable au moment de la compilation.Rather than convert a null to any type, the language defines that a null value won't match any type pattern, regardless of the compile-time type of the variable. En raison de ce comportement, le nouveau modèle de type basé sur switch est cohérent par rapport à l’instruction is : les instructions is retournent toujours false quand la valeur vérifiée est null.This behavior makes the new switch based type pattern consistent with the is statement: is statements always return false when the value being checked is null. Il est aussi plus simple : une fois le type vérifié, aucun autre contrôle de valeur Null n’est nécessaire.It's also simpler: once you've checked the type, you don't need an additional null check. On constate en effet qu’aucune vérification de ce type ne figure dans les blocs de cas des exemples ci-dessus : ces contrôles ne sont pas requis dans la mesure où la correspondance avec le modèle de type garantit une valeur non Null.You can see that from the fact that there are no null checks in any of the case blocks of the samples above: they aren't necessary, since matching the type pattern guarantees a non-null value.

Déclarations var dans les expressions casevar declarations in case expressions

L’introduction de var comme l’une des expressions de correspondance fournit de nouvelles règles pour les critères spéciaux.The introduction of var as one of the match expressions introduces new rules to the pattern match.

La première règle est que la déclaration var suit les règles standard d’inférence de type, à savoir que le type est supposé être le type statique de l’expression switch.The first rule is that the var declaration follows the normal type inference rules: The type is inferred to be the static type of the switch expression. Avec cette règle, il y a toujours correspondance du type.From that rule, the type always matches.

La deuxième règle est qu’une déclaration var n’a pas le contrôle de valeur Null que comportent d’autres expressions de modèle de type.The second rule is that a var declaration doesn't have the null check that other type pattern expressions include. La variable peut donc être Null, et une vérification de valeur Null est alors nécessaire.That means the variable may be null, and a null check is necessary in that case.

Ces deux règles signifient que, dans de nombreux cas, une déclaration var dans une expression case remplit les mêmes conditions qu’une expression default.Those two rules mean that in many instances, a var declaration in a case expression matches the same conditions as a default expression. Étant donné qu’une expression case non définie par défaut est toujours préférée à l’expression case default, l’expression case default n’est jamais exécutée.Because any non-default case is preferred to the default case, the default case will never execute.

Notes

Le compilateur n’émet pas d’avertissement pour signaler qu’une expression case default écrite ne peut pas s’exécuter.The compiler does not emit a warning in those cases where a default case has been written but will never execute. Cela est cohérent avec le comportement actuel de l’instruction switch où tous les cas possibles ont été répertoriés.This is consistent with current switch statement behavior where all possible cases have been listed.

La troisième règle présente les cas où l’utilisation d’une expression case var peut être appropriée.The third rule introduces uses where a var case may be useful. Supposons que vous utilisiez des critères spéciaux dont l’entrée est une chaîne et que vous recherchiez des valeurs de commande connues.Imagine that you're doing a pattern match where the input is a string and you're searching for known command values. Vous pouvez écrire un code similaire à celui-ci :You might write something like:

static object CreateShape(string shapeDescription)
{
    switch (shapeDescription)
    {
        case "circle":
            return new Circle(2);

        case "square":
            return new Square(4);
        
        case "large-circle":
            return new Circle(12);

        case var o when (o?.Trim().Length ?? 0) == 0:
            // white space
            return null;
        default:
            return "invalid shape description";
    }            
}

L’instruction case var correspond à une valeur null, une chaîne vide ou une chaîne composée uniquement d’espaces blancs.The var case matches null, the empty string, or any string that contains only white space. On remarque que le code ci-dessus utilise l’opérateur ?. pour empêcher la levée accidentelle d’une NullReferenceException.Notice that the preceding code uses the ?. operator to ensure that it doesn't accidentally throw a NullReferenceException. Le cas default gère toutes les autres valeurs de chaîne qui ne sont pas comprises par cet analyseur de commande.The default case handles any other string values that aren't understood by this command parser.

Il s’agit d’un exemple où vous pouvez envisager d’utiliser une expression case var différente d’une expression default.This is one example where you may want to consider a var case expression that is distinct from a default expression.

ConclusionsConclusions

Les constructions de critères spéciaux permettent de gérer facilement le flux de contrôle entre différents types et variables qui ne sont pas liés par une hiérarchie d’héritage.Pattern Matching constructs enable you to easily manage control flow among different variables and types that aren't related by an inheritance hierarchy. Vous pouvez également contrôler la logique pour utiliser n’importe quelle condition testée sur la variable.You can also control logic to use any condition you test on the variable. Ces constructions permettent d’utiliser les modèles et les idiomes dont vous aurez davantage besoin à mesure que vous créez d’autres applications distribuées, où les données et les méthodes qui les manipulent sont séparées.It enables patterns and idioms that you'll need more often as you build more distributed applications, where data and the methods that manipulate that data are separate. Vous remarquerez que les structs de formes utilisés dans cet exemple ne contiennent pas de méthodes, mais seulement des propriétés en lecture seule.You'll notice that the shape structs used in this sample don't contain any methods, just read-only properties. Les critères spéciaux peuvent être utilisés avec tous les types de données.Pattern Matching works with any data type. Vous écrivez des expressions qui examinent l’objet et vous prenez des décisions de flux de contrôle en fonction de ces conditions.You write expressions that examine the object, and make control flow decisions based on those conditions.

Comparez le code de cet exemple avec la conception qui résulterait de la création d’une hiérarchie de classes pour une Shape abstraite et des formes dérivées spécifiques, chacune avec sa propre implémentation d’une méthode virtuelle pour calculer la surface.Compare the code from this sample with the design that would follow from creating a class hierarchy for an abstract Shape and specific derived shapes each with their own implementation of a virtual method to calculate the area. Les expressions de critères spéciaux vous seront souvent d’une grande utilité quand vous voudrez manipuler des données en gérant les questions de stockage de données séparément des questions de comportement.You'll often find that pattern matching expressions can be a very useful tool when you're working with data and want to separate the data storage concerns from the behavior concerns.