with expression - Yok edici olmayan mutasyon değiştirilmiş özelliklere sahip yeni bir nesne oluşturur

İfade with , belirtilen özelliklerin ve alanların değiştirildiği işleneninin bir kopyasını oluşturur. Hangi üyelerin değiştirileceğini ve yeni değerlerini belirtmek için nesne başlatıcı söz dizimini kullanırsınız:

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 }
    }
}

bir ifadenin sol işleneni with bir kayıt türünde olabilir. C# 10'dan başlayarak, bir with ifadenin sol tarafında işlenen bir yapı türünde veya anonim bir türde de olabilir.

Bir ifadenin with sonucu, aşağıdaki örnekte gösterildiği gibi ifadenin işleneni ile aynı çalışma zamanı türüne sahiptir:

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 }
    }
}

Başvuru türündeki bir üye söz konusu olduğunda, bir işlenen kopyalandığında yalnızca üye örneğine yapılan başvuru kopyalanır. Hem kopya hem de özgün işlenen aynı başvuru türü örneğine erişebilir. Aşağıdaki örnekte bu davranış gösterilmektedir:

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
    }
}

Özel kopyalama semantiği

Herhangi bir kayıt sınıfı türünde kopya oluşturucu vardır. Kopya oluşturucu, içeren kayıt türünün tek bir parametresine sahip bir oluşturucudur. Bağımsız değişkeninin durumunu yeni bir kayıt örneğine kopyalar. bir with ifadenin değerlendirilmesinde, özgün kaydı temel alan yeni bir kayıt örneğini oluşturmak için kopya oluşturucu çağrılır. Bundan sonra, yeni örnek belirtilen değişikliklere göre güncelleştirilir. Varsayılan olarak, kopya oluşturucu örtük, yani derleyici tarafından oluşturulmuştur. Kayıt kopyalama semantiğini özelleştirmeniz gerekiyorsa, istenen davranışa sahip bir kopya oluşturucuyu açıkça bildirin. Aşağıdaki örnek, önceki örneği açık bir kopya oluşturucuyla güncelleştirir. Yeni kopyalama davranışı, bir kayıt kopyalandığında liste başvurusu yerine liste öğelerini kopyalamaktır:

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
    }
}

Yapı türleri için kopyalama semantiğini özelleştiremezsiniz.

C# dili belirtimi

Daha fazla bilgi için kayıtların özellik teklifi notunun aşağıdaki bölümlerine bakın:

Ayrıca bkz.