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.
Výraz
Výraz with vytvoří kopii svého operandu se zadanými vlastnostmi a upravenými poli. Pomocí syntaxe inicializátoru objektů určete, které členy se mají upravit, a jejich nové hodnoty:
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 }
}
}
Levý operand výrazu with může být typ záznamu. Může to být také typ struktury nebo anonymní typ.
Referenční dokumentace jazyka C# dokumentuje naposledy vydané verze jazyka C#. Obsahuje také počáteční dokumentaci k funkcím ve verzi Public Preview pro nadcházející jazykovou verzi.
Dokumentace identifikuje všechny funkce, které byly poprvé představeny v posledních třech verzích jazyka nebo v aktuálních verzích Public Preview.
Návod
Informace o tom, kdy byla funkce poprvé představena v jazyce C#, najdete v článku o historii verzí jazyka C#.
Výsledek výrazu with má stejný typ běhu jako operand výrazu, jak ukazuje následující příklad:
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 }
}
}
Pokud je členem typ odkazu, zkopíruje tento člen pouze odkaz na tuto instanci člena. Kopie i původní operand mají přístup ke stejné instanci typu odkazu. Následující příklad ukazuje toto chování:
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
}
}
Vlastní sémantika kopírování
Každý typ třídy záznamu má konstruktor kopírování.
konstruktor kopírování je konstruktor s jedním parametrem obsahujícího typ záznamu. Zkopíruje stav svého argumentu do nové instance záznamu. Při vyhodnocování výrazu with volá konstruktor kopírování k vytvoření nové instance záznamu na základě původního záznamu. Potom aktualizuje novou instanci se zadanými úpravami. Ve výchozím nastavení kompilátor syntetizuje konstruktor kopírování. Chcete-li přizpůsobit sémantiku kopírování záznamu, explicitně deklarujte konstruktor kopírování s požadovaným chováním. Následující příklad aktualizuje předchozí příklad pomocí explicitního konstruktoru kopírování. Nové chování kopírování kopíruje položky seznamu místo odkazu na seznam při kopírování záznamu:
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
}
}
Sémantika kopírování pro typy struktur se nedá přizpůsobit.
Důležité
V předchozích příkladech jsou všechny vlastnosti nezávislé. Žádná z vlastností se nevypočítá z jiných hodnot vlastností. Výraz with nejprve zkopíruje existující instanci záznamu a potom upraví všechny vlastnosti nebo pole zadaná ve výrazu with . Vypočítané vlastnosti v record typech by se měly vypočítat při přístupu, ne inicializovat při vytvoření instance. V opačném případě může vlastnost vrátit vypočítanou hodnotu na základě původní instance, nikoli upravené kopie. Další informace najdete v článku s referenčními informacemi o record typech.
Specifikace jazyka C#
Další informace najdete v následujících částech záznamu návrhu funkce:
Viz také
- operátory a výrazy jazyka C#
- záznamů
- typy struktury