C#3.0:自动属性 ​​- 编译器创建的私有变量的名称是什么

Shy*_*yju 8 automatic-properties c#-3.0

我正在检查.NET 3.5的新功能,发现在C#3.0中,我们可以使用

public class Person 
{    
 public string FirstName  { get; set; }
 public string LastName  { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

代替

private string name;

public string Name
{
  get { return name; }
  set { name = value; }
}
Run Code Online (Sandbox Code Playgroud)

如果我使用自动属性,名称的私有变量名称是什么?互联网上的教程说编译器会自动创建一个私有变量.那么我如何使用/访问私有变量,如果我想在这个类的方法中使用它?

ang*_*son 19

改写得更清楚

该字段生成正常,但您的代码作为常规字段不可见.

这是您典型的自动属性:

public string FirstName  { get; set; }
Run Code Online (Sandbox Code Playgroud)

如果我们查看已编译的程序集,则会生成此后备存储字段:

[CompilerGenerated]
private string <FirstName>k__BackingField;
Run Code Online (Sandbox Code Playgroud)

请注意那里的<和>,它们不是您可以在自己的字段名称中使用的字符.您也无法访问该字段,因为在查看您的代码时,编译器所关注的字段并不"存在".

这里真正的问题,从我来说,为什么你想进入这一领域.换句话说,为什么需要访问该字段,以及它对访问该属性的代码有何作用?

如果你想阻止对字段的外部写访问,那么通过将setter方法设为私有,这很容易实现,如下所示:

public string FirstName  { get; private set; }
Run Code Online (Sandbox Code Playgroud)

请注意,由于该字段实际上存在于程序集中,这意味着这不是JITter魔术,而是编译器魔术,因此您可以使用反射来查找和访问该字段.

但同样,你为什么要这样做?

现在,让我们假设您确实有合理的理由想要使用该字段而不是属性.我可以想到一个,虽然我可能会采用不同的方式,那就是你想将字段名称作为out或ref参数传递给方法,如下所示:

public void AdjustName(ref String name)
{
    name = Capitalize(name);
}
Run Code Online (Sandbox Code Playgroud)

您不能将属性作为out/ref-parameters传递,因此此代码不起作用:

AdjustName(ref string FirstName);
Run Code Online (Sandbox Code Playgroud)

在这种情况下,您需要回退到定义属性的"旧"方式,手动添加后备存储字段,如下所示:

private string firstName;
public string FirstName
{
    get { return firstName; }
    set { firstName = value; }
}
Run Code Online (Sandbox Code Playgroud)

有了这个,您可以调用该方法:

AdjustName(ref string firstName); // note the field, not the property
Run Code Online (Sandbox Code Playgroud)

但是,我可能会更改该方法以返回新值,而不是直接调整引用的变量.


Ach*_*him 5

如前所述:您无法访问自动生成的变量(不使用坏技巧)。但我假设您问这个问题是因为您只想拥有一个 getter,但仍想使用自动属性……对吗?在这种情况下,你可以使用这个:

public string FirstName  { get; private set; }
Run Code Online (Sandbox Code Playgroud)

现在你有一个私有的 setter 和一个公共的 getter。