badweasel badweasel - 8 days ago 4
C# Question

what the best way to declare a property

I'm switching from Objective-C to C# to start using the Unity engine. So I'm trying to soak in all the C# differences. Obj-C has the @synthesize that auto creates the getters and setters. To to be honest they're sort of new to me. In Obj-C I'd often do:

@synthesize myProperty = _myProperty;


Then use the
_myProperty
in the local class code and access that property outside of this class using
myProperty
. Or more accurately
classInstance.myProperty
.

Also in Obj-C you can declare a property to be
readonly
and not worry about accidentally changing it's value outside the class.

In C# I'm trying to write proper object oriented code and I struggle with this. I'm a C coder at heart and am comfortable having access to everything everywhere, which I know is bad and unnecessary. I also don't want to expose tons of properties to the GameObject Inspector. I prefer to do as much programmatically as possible.

So what is the best way to declare properties so I can access them from another class but also so they are not exposed in the Inspector? Here are some possibilities that I've encountered and used:

// 1. public static - public without being exposed in inspector
public static int myProperty;

// 2. the public _text doesn't appear in the inspector but the text one does.
public string _text;
public string text {
get { return _text; }
set {
_text = value;
}
}

// 3. private _underscore version with no setter - does removing the set make it read only?
private float _current;
public float current {
get { return _current; }
}

// 4. creating my own getter function
private int myValue;
...
int GetMyValue() {
return myValue;
}


Also.. I read somewhere that in .NET you shouldn't use underscores in property names. I don't really know what the underscore version of the property does or represents. I thought in Obj-C it effected the scope, but don't really know.

Am I even correct in calling variables properties?

Someone suggested prop tab tab which produces this:

public object MyProperty {
get;
set;
}


Unfortunately that doesn't really answer my question about read only. Is an int or string even an object? It's not in Obj-C.

Answer

The NonSerialized and HideInspector attributes are the two options you must consider to hide members of the class from the Unity inspector. NonSerialized is not specific to Unity, HideInspector is specific to Unity. Unity looks for both of these attribute in your compiled code to determine what gets exposed in the inspector.

If you want a publicly read only property you declare it like so...

[System.NonSerialized]
private string _text;

/// <summary>
/// Gets the Text
/// </summary>
/// <remarks>May be set within this class or derived classes</remarks>
public string Text {
    get { return _text; }
    protected set {
        _text = value;
    }
}

You seem to be having issues with the meaning of access modifiers...

See this page...

https://msdn.microsoft.com/en-us/library/wxh6fsc7.aspx

Briefly...

  • public = accessible from anywhere, do not declare backing variables on properties as public, otherwise people can simply skip your property accessor.
  • protected = accessible within your class and from classes inheriting the class
  • internal = accessible within the same assembly
  • protected internal = accessible within the same assembly and from classes inheriting the class
  • private = accessible only within your class

You can do away with backing variables simply by declaring

/// <summary>
/// Gets or sets the Text
/// </summary>
public string Text { get; set; }

/// <summary>
/// Gets the current
/// </summary>
public float Current { get; protected set; }

Since the advent of auto-implemented variables, there are no technical reasons for creating properties with backing variables unless you have additional logic you would like executed on the get and/or set.

e.g you wanted to create Observable entities that raise an event when a property is changed...

    private int _id;

    public int ID
    {
        get
        {
            return _id;
        }
        set
        {
            if (_id != value)
            {
                OnIDChanging(value);
                ReportPropertyChanging("ID");
                _id = StructuralObject.SetValidValue(value);
                ReportPropertyChanged("ID");
                OnIDChanged();
            }
        }
    }

In terms of coding standards, there are plenty of them on the net. I'd recommend IDesign's...

http://www.idesign.net/downloads/getdownload/1985

You'll notice I changed the casing on the code you posted, the casing I've used adhere's to IDesign's naming guidelines