Public struct GridPosition fields

I noticed you are using public fields inside of GridPosition. wouldn’t it be better to instead make them private backing fields that are accessed by public properties in order to promote encapsulation?

For simple “data class” types like GridPosition, it’s acceptable (and typical) to use public data members, since the type is used as a complex “value” rather than for “behaviour” (which would use a class, typically). If values are in a struct so that they are simply bunched together, they can be get/set directly and there’s no real benefit to encapsulation.

But there’s a line somewhere between a “simple” type and a more complex type (and structs are handled differently to class instances, in C#, so there are other aspects to consider too), so part of the skill is choosing the right representation for your data. You may want to change a struct to a class if it gets too complex, for example. Experience helps with this, but you can always refactor later.

1 Like

Yup a struct is not meant to be a complex object, just as simple way to structure some data so it makes sense to treat it kind of like a basic variable that splits its own data into multiple pieces.

1 Like

Also, if you really want to use properties, you can forego the backing variable and let the compiler make it for you with an auto property

public int x { get; set; }
public int z { get; set; }

piwakawaka, What you say makes sense; but I 've read in several books and articles (such as c# in a nutshell) that you should always use public properties over public fields; there are some exceptions to this rule such as using static readonly fields. Here is an excerpt from a book explaining this: Why Properties Matter.

bixarrio: Yes that is true; the complier will create a hidden private backing field for you. But, I would use an upper case X and Z instead so I would know it’s a property.

1 Like

yeah, I just made them lowercase because Unity does it like that. Personally, I have them as uppercase

Yeah, I see that a lot in unity; I wonder why it does that?

A naming convention is not a natural law. There are countless of naming conventions out there. Sometimes, you’ll also find “exotic” namings such as m_name in the Unity API. Since hundreds of programmers have been developing that game engine for more than 10 years, there are lots of inconsistencies.

Most people in the Unity community (not just here but also elsewhere on the internet) prefer lowercase for everything that looks like a variable and uppercase for methods. Usually, it’s a good idea to follow the established naming convention of a community because that makes communicating with people of the community easier. However, if you prefer uppercase for properties, that’s also fine as long as your namings remain consistent. :slight_smile:


See also:

You are right; naming conventions are not a natural law; but they do have standards;

the major way that Unit deviates from these standards seems to involve properties.
So the reason I believe Unity decided to do this deviation was for organizational reasons. Unity decided to categorize Properties as being both fields and property types. And Since the two are in the same category Unity must have decided to make them share the same naming convention; and they logically decided to use the lowercase first letter used by a typical field. I assume people using Unity also decided to follow this convention to avoid confusion…but that’s just a guess.

As a rule of thumb, in structs I tend to just use public variables, and in classes use getters and setters. As Hugo pointed out, structs are intended for the passing and sharing of data, where classes usually attach some functionality to the data.
It should be noted that one of the most compelling reasons for encapsulating data (using getters and setters) becomes moot with some of the more common uses of structs.

We encapsulate the data so that the class has control over the modification of the data. So in a class like Health, we want to avoid

public int healthPoints;

because we don’t want another class to modify healthPoints without going through a formal method like Damage. It’s about control.
Structs are a bit different, at least once they are passed as parameters. Unless a struct is passed with the ref keyword, a copy of the struct is put in the stack rather than a pointer to the struct… Consider the following:

public struct MyStruct
{
    public int a;
    public int b;
}
public void DoSomethingToStruct(MyStruct s)
{
   s.a=1;
   s.b=2;
   Debug.Log($"{s.a}/{s.b}");
}
void Start()
{
    MyStruct s = new MyStruct {a=3, b=4};
    DoSomethingToStruct(s);
    Debug.Log($"{s.a}/{s.b}");
}

Now if you ran this code, you would get an interesting result…
As you might expect, the first Debug.Log would read 1/2
This is because we modified the struct passed in DoSomethingToStruct(), and then printed the result.
On the other hand, immediately after that in Start, we Debug out the state of the struct, and even though we passed it in DoSomethingToStruct, and DoSomethingToStruct totally modified the values, the second Debug will read “3/4”
This is because a copy was placed on the stack for DoSomethingToStruct to play with, and the original struct declared in Start was never touched.

2 Likes

You made some really good points and I can see why you do it that way; but you seem to handle structs similar to the way that C++ handles them (nothing wrong with that;) It’s struct members are public by default so it’s usually okay to make them public (classes are private by default.) But; C# class and struct members are both “private” by default. And since it really isn’t that much more difficult to make fields private with the aid of public properties/ automatic properties (plus other benefits) I don’t see the need to make them public.

As far as your code goes, the struct seemed to work the way I would expect it to since it is a value type. And, of course, it differs from the (reference type) class. But, I think that might have been your point.

Indeed, it was. I got cut short on time, so didn’t get to finish the whole post…
If you took that same code and changed struct to class, the resulting Debugs would both read
1/1
This is because classes are always passed by reference. The same would also happen if you modified the functions with the ref keyword.

1 Like

This topic was automatically closed 20 days after the last reply. New replies are no longer allowed.

Privacy & Terms