Anteckning
Åtkomst till den här sidan kräver auktorisering. Du kan prova att logga in eller ändra kataloger.
Åtkomst till den här sidan kräver auktorisering. Du kan prova att ändra kataloger.
Uttrycket
Ett with uttryck skapar en kopia av dess operand med de angivna egenskaperna och fälten ändrade. Du använder syntaxen objektinitierare för att ange vilka medlemmar som ska ändras och deras nya värden:
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 }
var apples = new { Item = "Apples", Price = 1.19m };
Console.WriteLine($"Original: {apples}"); // output: Original: { Item = Apples, Price = 1.19 }
var saleApples = apples with { Price = 0.79m };
Console.WriteLine($"Sale: {saleApples}"); // output: Sale: { Item = Apples, Price = 0.79 }
}
}
Den vänstra operanden för ett with uttryck kan vara av posttyp. En vänsteroperation av ett with-uttryck kan också vara av strukturtyp eller en anonym typ.
Resultatet av ett with-uttryck har samma körningstidstyp som uttryckets operand, som följande exempel visar:
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 }
}
}
När en medlem är en referenstyp kopieras endast referensen till en medlemsinstans när en operand kopieras. Både kopian och den ursprungliga operanden har åtkomst till samma referenstypsinstans. Följande exempel visar det beteendet:
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
}
}
Anpassad kopieringssemantik
Alla postklasstyper har kopieringskonstruktorn. En kopieringskonstruktor är en konstruktor med en enda parameter av den innehållande rekordtypen. Det kopierar tillståndet av sitt argument till en ny objektinstans. Vid utvärdering av ett with-uttryck anropas kopieringskonstruktorn för att skapa en ny instans av en post baserad på en ursprunglig post. Därefter uppdateras den nya instansen enligt de angivna ändringarna. Som standard är kopieringskonstruktorn implicit, d.v.s. kompilatorgenererad. Om du behöver anpassa postkopieringssemantiken deklarerar du uttryckligen en kopieringskonstruktor med önskat beteende. I följande exempel uppdateras föregående exempel med en explicit kopieringskonstruktor. Det nya kopieringsbeteendet är att kopiera listobjekt i stället för en listreferens när en post kopieras:
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
}
}
Du kan inte anpassa kopieringssemantiken för strukturtyper.
Viktigt!
I föregående exempel är alla egenskaper oberoende. Ingen av egenskaperna beräknas från andra egenskapsvärden. Ett with uttryck kopierar först den befintliga postinstansen with och ändrar sedan alla egenskaper eller fält som anges i uttrycket. Beräknade egenskaper i record typer ska beräknas vid åtkomst, inte initieras när instansen skapas. Annars kan en egenskap returnera det beräknade värdet baserat på den ursprungliga instansen, inte den ändrade kopian. Mer information finns i språkreferensartikeln om record typer.
Språkspecifikation för C#
Mer information finns i följande avsnitt i -posternas funktionsförslagsanteckning: