Nota
L'accés a aquesta pàgina requereix autorització. Pots provar d'iniciar sessió o canviar de directori.
L'accés a aquesta pàgina requereix autorització. Pots provar de canviar directoris.
La
Una with expresión crea una copia de su operando con las propiedades y campos especificados modificados. Use la sintaxis del inicializador de objeto para especificar qué miembros modificar y sus nuevos valores:
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 }
}
}
El operando izquierdo de una with expresión puede ser un tipo de registro. También puede ser un tipo de estructura o un tipo anónimo.
La documentación de referencia del lenguaje C# cubre la versión más reciente publicada del lenguaje C#. También contiene documentación inicial sobre las características de las versiones preliminares públicas de la próxima versión del lenguaje.
La documentación identifica cualquier característica introducida por primera vez en las últimas tres versiones del idioma o en las versiones preliminares públicas actuales.
Sugerencia
Para buscar cuándo se introdujo por primera vez una característica en C#, consulte el artículo sobre el historial de versiones del lenguaje C#.
El resultado de una with expresión tiene el mismo tipo en tiempo de ejecución que el operando de la expresión, como se muestra en el ejemplo siguiente:
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 }
}
}
Cuando un miembro es un tipo de referencia, copiar ese miembro copia solo la referencia a esa instancia de miembro. Tanto el operando copy como el original acceden a la misma instancia de tipo de referencia. En el ejemplo siguiente se muestra ese comportamiento:
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
}
}
Semántica de copia personalizada
Cada tipo de clase de registro tiene un constructor de copia. Un constructor de copia es un constructor con un único parámetro del tipo de registro contenedor. Copia el estado de su argumento en una nueva instancia de registro. Al evaluar una with expresión, llama al constructor de copia para crear una nueva instancia de registro basada en un registro original. A continuación, actualiza la nueva instancia con las modificaciones especificadas. De forma predeterminada, el compilador sintetiza el constructor de copia. Para personalizar la semántica de copia de registros, declare explícitamente un constructor de copia con el comportamiento deseado. En el ejemplo siguiente se actualiza el ejemplo anterior con un constructor de copia explícito. El nuevo comportamiento de copia copia elementos de lista en lugar de una referencia de lista cuando se copia un registro:
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
}
}
No se puede personalizar la semántica de copia para los tipos de estructura.
Importante
En los ejemplos anteriores, todas las propiedades son independientes. Ninguna de las propiedades se calcula desde otros valores de propiedad. Una with expresión copia primero la instancia de registro existente y, a continuación, modifica las propiedades o campos especificados en la with expresión. Las propiedades calculadas de record los tipos deben calcularse en el acceso, sin inicializarse cuando se crea la instancia. De lo contrario, una propiedad podría devolver el valor calculado en función de la instancia original, no la copia modificada. Para obtener más información, consulte el artículo de referencia del lenguaje sobre record tipos.
Especificación del lenguaje C#
Para obtener más información, consulte las secciones siguientes de la nota de propuesta de características de registros: