Pra*_*r J 10 c# primary-constructor .net-8.0 c#-12.0
我正在使用 C# 12。在 C# 12 中我可以使用主构造函数:
实施1:
public class Calculation(int a,int b)
{
public int Addition() => a + b;
public int Subtraction() => a - b;
}
Run Code Online (Sandbox Code Playgroud)
实施2:
public class Calculation(int a,int b)
{
private int _a { get; init; } = a;
private int _b { get; init; } = b;
public int Addition() => _a + _b;
public int Subtraction() => _a - _b;
}
Run Code Online (Sandbox Code Playgroud)
当我像这样调用这个方法时:
console.WriteLine(new Calculation(10,25).Addition());
Run Code Online (Sandbox Code Playgroud)
两种实现都工作正常,所以我想知道使用较长的实现 2 相对于较短的实现 1 是否有任何优势。
Gur*_*ron 12
以这种方式自己创建字段/属性是没有意义的,因为在这种情况下编译器会为您创建它们(反编译@sharplab.io)。
来自教程:探索主构造函数文档(它们使用struct
但类的主构造函数的处理基本相同):
Run Code Online (Sandbox Code Playgroud)public struct Distance(double dx, double dy) { public readonly double Magnitude => Math.Sqrt(dx * dx + dy * dy); public readonly double Direction => Math.Atan2(dy, dx); public void Translate(double deltaX, double deltaY) { dx += deltaX; dy += deltaY; } public Distance() : this(0,0) { } }
在前面的示例中,主要构造函数属性是在方法中访问的。因此,编译器创建隐藏字段来表示每个参数。以下代码大致显示了编译器生成的内容。实际的字段名称是有效的 CIL 标识符,但不是有效的 C# 标识符。
Run Code Online (Sandbox Code Playgroud)public struct Distance { private double __unspeakable_dx; private double __unspeakable_dy; public readonly double Magnitude => Math.Sqrt(__unspeakable_dx * __unspeakable_dx + __unspeakable_dy * __unspeakable_dy); public readonly double Direction => Math.Atan2(__unspeakable_dy, __unspeakable_dx); public void Translate(double deltaX, double deltaY) { __unspeakable_dx += deltaX; __unspeakable_dy += deltaY; } public Distance(double dx, double dy) { __unspeakable_dx = dx; __unspeakable_dy = dy; } public Distance() : this(0, 0) { } }
潜在的缺点是生成的字段是可变的:
public class Calculation(int a, int b)
{
public void Mutate() => a = 100;
// ...
}
Run Code Online (Sandbox Code Playgroud)
尽管您的方法并不能解决这个问题,但当您混淆_a
和时,会带来一些混乱a
。目前无法标记生成的字段readonly
(但有该功能的计划 - 请参阅此 LDM 注释文档和此提案),但您可以通过使用具有相同名称(或属性)的字段来隐藏 ctor 参数:
public class Calculation2(int a, int b)
{
private readonly int a = a;
private readonly int b = b;
// public void Mutate() => a = 100; // does not compile
public int Addition() => a + b;
public int Subtraction() => a - b;
}
Run Code Online (Sandbox Code Playgroud)
也可以看看:
第二种实现的优点: