在C#9中,可以在其主要构造函数及其主体中的记录中定义一个具有相同名称的属性:
record Cat(int PawCount)
{
public int PawCount { get; init; }
}
这段代码编译没有错误。初始化此类记录的实例时,将完全忽略提供给构造函数的值:
Console.WriteLine(new Cat(4));
Console.WriteLine(new Cat(4) { PawCount = 1 });
打印Cat { PawCount = 0 }
Cat { PawCount = 1 }
这种行为是正确的还是错误?
如果正确,在什么情况下有用?
我希望编译器拒绝该代码,并产生类似“类型
Cat
已经包含PawCount
的定义”之类的错误,或者考虑构造函数和主体中的属性相同,并从构造函数中执行其初始化。后一种变体可能非常有用,可以为属性提供自定义的getter和/或初始化器,而不必在其主体中重写位置记录的所有属性。
实际的行为对我来说毫无意义。
最佳答案
正确的方法是:
record Cat(int PawCount)
{
public int PawCount { get; init; } = PawCount;
}
这很有用,因为它允许您执行例如验证record Cat(int PawCount)
{
private int _pawCount;
public int PawCount {
get => _pawCount;
init => _pawCount = value < 0 ? throw new ArgumentException() : value;
} = PawCount;
}
规范在这里:https://github.com/dotnet/csharplang/blob/master/proposals/csharp-9.0/records.md#members-of-a-record-typeMembers are synthesized unless a member with a "matching" signature is declared in the record body or an accessible concrete non-virtual member with a "matching" signature is inherited. Two members are considered matching if they have the same signature or would be considered "hiding" in an inheritance scenario.
因此,由于已经存在与该参数同名的属性,因此编译器将不会合成
PawCount
属性,因此除非您自己明确使用该参数,否则它会默默地忽略该参数。
关于c# - 两次定义记录中的属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65110563/