4

I noticed that in the Microsoft.Xna.Framework.Rectangle struct, there are plenty of properties that are just public int Bottom { get; } or public Point Center { get; }. I, for the life of me, can't figure out what's going on here. I've tried replicating this in some of my own structs, but I can't figure out how to give it a value in the first place without the set; keyword. What is it that the Rectangle struct is doing to {get;}?

dub stylee
  • 3,252
  • 5
  • 38
  • 59
Neil West
  • 63
  • 7
  • If there is no `set;` specified, then you will have to set the value using an alternative means. You can either set the value in the constructor, or you can make your own "setter" method to set the value for you. – dub stylee May 27 '15 at 22:53
  • 2
    Where are you seeing this code? Visual studio may be showing you the public interface. There may be private setters, or a `get` implementation, that you can't see. – Blorgbeard May 27 '15 at 22:56
  • 2
    For example, [this page](https://msdn.microsoft.com/en-us/library/microsoft.xna.framework.rectangle.bottom.aspx) says `public int Bottom { get; }`, however, that's just the public interface. It doesn't mean that the property is auto-implemented, it's just saying that there's a public getter and no public setter. – Blorgbeard May 27 '15 at 23:00

3 Answers3

1

It means the underlying value that the property gives you access to cannot be set later on.. you can only "get" the underlying value.

When you instantiate a Rectangle, you have to pass it a few values:

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

My guess (without looking at the source code) is that the property values (Center, Bottom, etc) are all set in the constructor. You can't alter them later on.. either look for another property to set (i.e. X or Y), or create a new Rectangle based on the existing one.

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

For comparison, here's a portion of the source code from the System.Drawing.Rectangle struct, which is probably fairly close to what you're dealing with. Notice that you can set certain values via the constructor, which are then stored in private variables, and are accessible (but only changeable in some) properties.

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

    ...
    ...
}
Grant Winney
  • 65,241
  • 13
  • 115
  • 165
1

The reason why the Rectangle.Bottom doesn't have a set is because it is a calculated value, Top + Height. If you would set that, what would you like to happen? Change the y position? Change the height? It is impossible to know. So you have to decide yourself and change the Top or Height based on what you actually want.

The idea of properties is not just to have a variable and set or get it. If it was we could just use public variables and that's it. Rather the idea is to allow validation and calculated properties.

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

As you can see, there is no need to set it to anything, since it will infer its value based on other values.

(Of course internally it will most likely not use the other properties, but rather the actual variables due to performance)

Sami Kuhmonen
  • 30,146
  • 9
  • 61
  • 74
0

Consider the following:

    private int myVar;

    public int MyProperty
    {
        get { return myVar; }
    }

Here you see an example, taken directly from Visual Studio's C# snippets, showing how to implement a get-only property. You need to set the 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. The purpose of such properties is to make a contractual statement about your object "this property cannot be set."

This is similar to having a private setter, however, you cannot enforce access modifiers in an interface definition. Therefore, this syntax serves a specific purpose when defining data contracts and object interfaces, and that is to say "this property cannot be set, by contract, and no subclass may expose a public setter as part of this contract."

As an aside, you can circumvent access modifiers using reflection, but this is not the common case (and 99% of the .NET developers out there are probably unaware of this fact.)

Typically backing fields are set via a constructor, via reflection, or as part of object initialization.

This is also core syntax, it forms the basis of modern syntactic sugar. Consider the following property definition:

    public int MyProperty { get; set; }

This is entirely syntactic sugar, and not actually valid for a C# 1.0 compiler. Today at compile time a backing field is generated on your behalf. Thus, the following syntax is only valid for interface definitions (as it would never return a meaningful value otherwise.)

    public int MyProperty { get; }

The above is an (invalid) attempt to create a read-only property using the newer auto-property syntax.

References:

  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
Community
  • 1
  • 1
Shaun Wilson
  • 8,727
  • 3
  • 50
  • 48