Ескертпе
Бұл бетке кіру үшін қатынас шегін айқындау қажет. Жүйеге кіруді немесе каталогтарды өзгертуді байқап көруге болады.
Бұл бетке кіру үшін қатынас шегін айқындау қажет. Каталогтарды өзгертуді байқап көруге болады.
Выражение with создает копию операнда с указанными свойствами и полями, измененными. Синтаксис инициализатора объектов используется для указания, какие члены должны быть изменены и какие новые значения заданы.
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 }
}
}
Левый операнд выражения with может быть типом записи . Левый операнд выражения with может быть типа структуры или анонимного типа .
Результат выражения with имеет тот же тип времени выполнения, что и операнды выражения, как показано в следующем примере:
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 }
}
}
Если элемент является ссылочным типом, при копировании операнда копируется только ссылка на экземпляр элемента. Как копия, так и исходный операнд имеют доступ к одному и тому же экземпляру ссылочного типа. В следующем примере демонстрируется это поведение:
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
}
}
Семантика настраиваемого копирования
Любой тип класса записи имеет конструктор копирования . Конструктор копирования — это конструктор с одним параметром содержащего типа записи. Он копирует состояние аргумента в новый экземпляр записи. Во время вычисления выражения with конструктор копирования вызывается для создания нового экземпляра записи на основе исходной записи. После этого новый экземпляр обновляется в соответствии с указанными изменениями. По умолчанию конструктор копирования неявен, т. е. создается компилятором. Если необходимо настроить семантику копирования записей, явно объявите конструктор копирования с требуемым поведением. Следующий пример обновляет предыдущий пример с явным конструктором копирования. Новое поведение копирования заключается в копировании элементов списка вместо ссылки на список при копировании записи:
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
}
}
Невозможно настроить семантику копирования для типов структур.
Это важно
В предыдущих примерах все свойства являются независимыми. Ни один из свойств не вычисляется из других значений свойств.
with Выражение сначала копирует существующий экземпляр записи, а затем изменяет все свойства или поля, указанные with в выражении. Вычисляемые свойства в record типах должны вычисляться при доступе, а не инициализироваться при создании экземпляра. В противном случае свойство может возвращать вычисляемое значение на основе исходного экземпляра, а не измененной копии. Дополнительные сведения см. в справочной статье о языках типовrecord.
Спецификация языка C#
Дополнительную информацию см. в следующих разделах заметки о предложении функции записей :