【问题标题】:how do i use a property { get; }?我如何使用属性 { get; }?
【发布时间】:2015-05-27 22:46:26
【问题描述】:

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

【问题讨论】:

  • 如果没有指定set;,那么您将不得不使用其他方式设置该值。您可以在构造函数中设置值,也可以创建自己的“setter”方法为您设置值。
  • 你在哪里看到这个代码? Visual Studio 可能会向您展示公共界面。可能有您看不到的私有 setter 或 get 实现。
  • 例如,this page 表示public int Bottom { get; },然而,这只是公共接口。这并不意味着该属性是自动实现的,只是说有一个公共 getter 而没有公共 setter。

标签: c# visual-studio-2013 xna


【解决方案1】:

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

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

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

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

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

【讨论】:

    【解决方案2】:

    这意味着属性允许您访问的基础值不能在以后设置..您只能“获取”基础值。

    当您实例化Rectangle 时,您必须向它传递一些值:

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

    我的猜测(不看源代码)是属性值(CenterBottom 等)都是在构造函数中设置的。您以后无法更改它们。或者寻找另一个要设置的属性(即XY),或者在现有属性的基础上创建一个新的Rectangle

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

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

    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; }
        }
    
        ...
        ...
    }
    

    【讨论】:

    • 我很确定这是一个计算值,没有在构造函数中设置,因为它会浪费内存。
    【解决方案3】:

    考虑以下几点:

        private int myVar;
    
        public int MyProperty
        {
            get { return myVar; }
        }
    

    您可以在此处看到一个示例,该示例直接取自 Visual Studio 的 C# sn-ps,展示了如何实现仅获取属性。您需要设置backing field,但无法通过该属性完成,因为该属性据说是a read-only propertya property with no setter method。此类属性的目的是就您的对象做出“无法设置此属性”的合同声明。

    这类似于拥有一个私有设置器,但是,您不能在接口定义中强制使用访问修饰符。因此,这种语法在定义数据契约和对象接口时有一个特定的目的,也就是说“这个属性不能通过契约来设置,并且任何子类都不能公开一个公共的 setter 作为这个契约的一部分。”

    顺便说一句,you can circumvent access modifiers using reflection,但这不是常见的情况(99% 的 .NET 开发人员可能不知道这个事实。)

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

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

        public int MyProperty { get; set; }
    

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

        public int MyProperty { get; }
    

    以上是使用较新的auto-property 语法创建read-only 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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-04-05
      • 2013-05-08
      • 1970-01-01
      • 2018-02-10
      • 1970-01-01
      • 2013-08-21
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多