espressione with (riferimenti per C#)with expression (C# reference)

Disponibile in C# 9,0 e versioni successive, un' with espressione produce una copia dell'operando del record con le proprietà e i campi specificati modificati:Available in C# 9.0 and later, a with expression produces a copy of its record operand with the specified properties and fields modified:

using System;

public class WithExpressionBasicExample
{
    public record NamedPoint(string Name, int X, int Y);

    public static void Main()
    {
        var p1 = new NamedPoint("A", 0, 0);
        Console.WriteLine($"{nameof(p1)}: {p1}");  // output: p1: NamedPoint { Name = A, X = 0, Y = 0 }
        
        var p2 = p1 with { Name = "B", X = 5 };
        Console.WriteLine($"{nameof(p2)}: {p2}");  // output: p2: NamedPoint { Name = B, X = 5, Y = 0 }
        
        var p3 = p1 with 
            { 
                Name = "C", 
                Y = 4 
            };
        Console.WriteLine($"{nameof(p3)}: {p3}");  // output: p3: NamedPoint { Name = C, X = 0, Y = 4 }

        Console.WriteLine($"{nameof(p1)}: {p1}");  // output: p1: NamedPoint { Name = A, X = 0, Y = 0 }
    }
}

Come illustrato nell'esempio precedente, si usa la sintassi dell' inizializzatore di oggetto per specificare quali membri modificare e i relativi nuovi valori.As the preceding example shows, you use object initializer syntax to specify what members to modify and their new values. In un' with espressione, un operando di sinistra deve essere di un tipo di record.In a with expression, a left-hand operand must be of a record type.

Il risultato di un' with espressione ha lo stesso tipo di runtime dell'operando dell'espressione, come illustrato nell'esempio seguente:The result of a with expression has the same runtime type as the expression's operand, as the following example shows:

using System;

public class InheritanceExample
{
    public record Point(int X, int Y);
    public record NamedPoint(string Name, int X, int Y) : Point(X, Y);

    public static void Main()
    {
        Point p1 = new NamedPoint("A", 0, 0);
        Point p2 = p1 with { X = 5, Y = 3 };
        Console.WriteLine(p2 is NamedPoint);  // output: True
        Console.WriteLine(p2);  // output: NamedPoint { X = 5, Y = 3, Name = A }
        
    }
}

Nel caso di un membro di tipo riferimento, quando viene copiato un record viene copiato solo il riferimento a un'istanza.In the case of a reference-type member, only the reference to an instance is copied when a record is copied. Sia la copia che il record originale hanno accesso alla stessa istanza di tipo riferimento.Both the copy and original record have access to the same reference-type instance. L'esempio seguente illustra questo comportamento:The following example demonstrates that behavior:

using System;
using System.Collections.Generic;

public class ExampleWithReferenceType
{
    public record TaggedNumber(int Number, List<string> Tags)
    {
        public string PrintTags() => string.Join(", ", Tags);
    }

    public static void Main()
    {
        var original = new TaggedNumber(1, new List<string> { "A", "B" });

        var copy = original with { Number = 2 };
        Console.WriteLine($"Tags of {nameof(copy)}: {copy.PrintTags()}");
        // output: Tags of copy: A, B

        original.Tags.Add("C");
        Console.WriteLine($"Tags of {nameof(copy)}: {copy.PrintTags()}");
        // output: Tags of copy: A, B, C
    }
}

Qualsiasi tipo di record ha il costruttore di copia.Any record type has the copy constructor. Si tratta di un costruttore con un solo parametro del tipo di record che lo contiene.That is a constructor with a single parameter of the containing record type. Copia lo stato del relativo argomento in una nuova istanza di record.It copies the state of its argument to a new record instance. Alla valutazione di un' with espressione, viene chiamato il costruttore di copia per creare un'istanza di una nuova istanza di record in base a un record originale.At evaluation of a with expression, the copy constructor gets called to instantiate a new record instance based on an original record. Successivamente, la nuova istanza viene aggiornata in base alle modifiche specificate.After that, the new instance gets updated according to the specified modifications. Per impostazione predefinita, il costruttore di copia è implicito, ovvero generato dal compilatore.By default, the copy constructor is implicit, that is, compiler-generated. Se è necessario personalizzare la semantica di copia dei record, dichiarare in modo esplicito un costruttore di copia con il comportamento desiderato.If you need to customize the record copy semantics, explicitly declare a copy constructor with the desired behavior. Nell'esempio seguente viene aggiornato l'esempio precedente con un costruttore di copia esplicito.The following example updates the preceding example with an explicit copy constructor. Il nuovo comportamento di copia consiste nel copiare gli elementi dell'elenco invece di un riferimento a un elenco quando viene copiato un record:The new copy behavior is to copy list items instead of a list reference when a record is copied:

using System;
using System.Collections.Generic;

public class UserDefinedCopyConstructorExample
{
    public record TaggedNumber(int Number, List<string> Tags)
    {
        protected TaggedNumber(TaggedNumber original)
        {
            Number = original.Number;
            Tags = new List<string>(original.Tags);
        }

        public string PrintTags() => string.Join(", ", Tags);
    }

    public static void Main()
    {
        var original = new TaggedNumber(1, new List<string> { "A", "B" });

        var copy = original with { Number = 2 };
        Console.WriteLine($"Tags of {nameof(copy)}: {copy.PrintTags()}");
        // output: Tags of copy: A, B

        original.Tags.Add("C");
        Console.WriteLine($"Tags of {nameof(copy)}: {copy.PrintTags()}");
        // output: Tags of copy: A, B
    }
}

Specifiche del linguaggio C#C# language specification

Per ulteriori informazioni, vedere le sezioni riportate di seguito della Nota sulla funzionalità relativa ai record:For more information, see the following sections of the records feature proposal note:

Vedere ancheSee also