And*_*ndi 10 c# c#-9.0 c#-record-type
record使用with关键字创建 C# 9 的新实例时,我想忽略某些字段,而不是将它们也复制到新实例中。
在以下示例中,我有一个Hash属性。因为它在计算上非常昂贵,所以它只在需要时才计算然后缓存(我有一个非常不可变的记录,所以对于一个实例,哈希永远不会改变)。
public record MyRecord {
// All truely immutable properties
public int ThisAndManyMoreComplicatedProperties { get; init; }
// ...
// Compute only when required, but then cache it
public string Hash {
get {
if (hash == null)
hash = ComputeHash();
return hash;
}
}
private string? hash = null;
}
Run Code Online (Sandbox Code Playgroud)
打电话时
MyRecord myRecord = ...;
var changedRecord = myRecord with { AnyProp = ... };
Run Code Online (Sandbox Code Playgroud)
changedRecord包含hash值 from myRecord,但我想要的null又是默认值。
是否有机会将该hash字段标记为“瞬态”/“内部”/“真正私有”...,或者我是否必须编写自己的复制构造函数来模仿此功能?
我找到了一种解决方法:您可以(ab)使用继承将复制构造函数分成两部分:手动部分仅用于hash(在基类中),而自动生成部分在派生类中复制所有有价值的数据字段。
这具有抽象出散列(非)缓存逻辑的额外优点。这是一个最小的例子(fiddle):
abstract record HashableRecord
{
protected string hash;
protected abstract string CalculateHash();
public string Hash
{
get
{
if (hash == null)
{
hash = CalculateHash(); // do expensive stuff here
Console.WriteLine($"Calculating hash {hash}");
}
return hash;
}
}
// Empty copy constructor, because we explicitly *don't* want
// to copy hash.
public HashableRecord(HashableRecord other) { }
}
record Data : HashableRecord
{
public string Value1 { get; init; }
public string Value2 { get; init; }
protected override string CalculateHash()
=> hash = Value1 + Value2; // do expensive stuff here
}
public static void Main()
{
var a = new Data { Value1 = "A", Value2 = "A" };
// outputs:
// Calculating hash AA
// AA
Console.WriteLine(a.Hash);
var b = a with { Value2 = "B" };
// outputs:
// AA
// Calculating hash AB
// AB
Console.WriteLine(a.Hash);
Console.WriteLine(b.Hash);
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
379 次 |
| 最近记录: |