我如何使用 属性 { get; }?

how do i use a property { get; }?

我注意到在 Microsoft.Xna.Framework.Rectangle struct 中,有很多属性只是 public int Bottom { get; }public Point Center { get; }。我,对于我的生活,无法弄清楚这里发生了什么。我已经尝试在我自己的一些结构中复制它,但我不知道如何在没有 set; 关键字的情况下首先给它一个值。 Rectangle struct{get;} 做了什么?

这意味着 属性 允许您访问的基础值以后无法设置。您只能 "get" 基础值。

当你实例化一个Rectangle时,你必须给它传递一些值:

public Rectangle (int x, int y, int width, int height)

我的猜测(没有查看源代码)是 属性 值(CenterBottom 等)都在构造函数中设置。你以后不能改变它们.. 要么寻找另一个 属性 来设置(即 XY),要么基于现有的 Rectangle 创建一个新的 Rectangle .

var newRect = new Rectangle(oldRect.X, oldRect.Y, oldRect.Width, oldRect.Height);

为了进行比较,这里是 System.Drawing.Rectangle 结构的一部分源代码,它可能与您正在处理的内容相当接近。请注意,您可以通过构造函数设置某些值,然后将其存储在私有变量中,并且可以访问(但在某些属性中只能 changeable)。

public struct Rectangle
{
    public static readonly Rectangle Empty = new Rectangle();

    private int x;
    private int y;
    private int width;
    private int height;

    public Rectangle(int x, int y, int width, int height)
    {
        this.x = x;
        this.y = y;
        this.width = width;
        this.height = height;
    }

    public int X
    {
        get { return x; }
        set { x = value; }
    }

    public int Left
    {
        get { return X; }
    }

    public int Y
    {
        get { return y; }
        set { y = value; }
    }

    public int Top
    {
        get { return Y; }
    }

    ...
    ...
}

考虑以下几点:

    private int myVar;

    public int MyProperty
    {
        get { return myVar; }
    }

在这里您可以看到一个示例,直接取自 Visual Studio 的 C# 片段,展示了如何实现只获取 属性。您需要设置backing field, but it cannot be done via the property because this property is said to be a read-only property or a property with no setter method。此类属性的目的是对您的对象作出合同声明"this property cannot be set."

这类似于私有 setter,但是,您不能在接口定义中强制使用访问修饰符。因此,这种语法在定义数据契约和对象接口时服务于特定目的,也就是说 "this property cannot be set, by contract, and no subclass may expose a public setter as part of this contract."

顺便说一句,you can circumvent access modifiers using reflection,但这并不常见(而且 99% 的 .NET 开发人员可能都没有意识到这一事实。)

通常 backing fields 通过构造函数、反射或作为对象初始化的一部分进行设置。

这也是核心语法,它构成了现代语法糖的基础。考虑以下 属性 定义:

    public int MyProperty { get; set; }

这完全是语法糖,实际上对 C# 1.0 编译器无效。今天编译时一个backing field is generated on your behalf。因此,以下语法仅对接口定义有效(否则它永远不会 return 一个有意义的值。)

    public int MyProperty { get; }

以上是创建 read-only property using the newer auto-property 语法的(无效)尝试。

参考文献:

  1. When should use Readonly and Get only properties
  2. Using a backing variable for getters and setters
  3. Is it possible to access backing fields behind auto-implemented properties?
  4. https://msdn.microsoft.com/en-us/library/bb384054.aspx
  5. https://msdn.microsoft.com/en-us/library/w86s7x04.aspx

Rectangle.Bottom之所以没有集合是因为​​它是一个计算值,Top + Height。如果你愿意设置它,你希望发生什么?改变y位置?改变高度?这是不可能知道的。因此,您必须自己决定并根据您的实际需要更改 TopHeight

属性的概念不仅仅是拥有一个变量并设置或获取它。如果是的话,我们可以只使用 public 变量,就是这样。相反,这个想法是允许验证和计算属性。

public int Bottom
{
  get { return Top + Height; }
}

如您所见,无需将其设置为任何值,因为它会根据其他值推断其值。

(当然在内部它很可能不会使用其他属性,而是由于性能而使用实际变量)