Basic

July 28 2020

0 comments

Unity C#: Expression-Bodied Members to Reduce Your Code Verbosity

By Rubén Torres Bonet

July 28, 2020


__CONFIG_colors_palette__{"active_palette":0,"config":{"colors":{"6c4de":{"name":"Main Accent","parent":-1},"67ed2":{"name":"Accent Dark","parent":"6c4de","lock":{"saturation":1}}},"gradients":[]},"palettes":[{"name":"Default","value":{"colors":{"6c4de":{"val":"var(--tcb-skin-color-0)"},"67ed2":{"val":"rgb(59, 65, 63)","hsl_parent_dependency":{"h":160,"l":-0.05,"s":0.04}}},"gradients":[]},"original":{"colors":{"6c4de":{"val":"rgb(51, 190, 127)","hsl":{"h":152,"s":0.57,"l":0.47}},"67ed2":{"val":"rgb(59, 65, 63)","hsl_parent_dependency":{"h":160,"s":0.04,"l":0.24}}},"gradients":[]}}]}__CONFIG_colors_palette__

Continuing with our Modern C# for Unity Game Development series, today I'm going to show you how to reduce the verbosity of your code with C# Expression-Bodied Members.

Note: this might upset some verbosity lovers out there 😏

What's Wrong With This Damn Code?

Imagine you want to keep your player data synchronized with a server.

(Such a rare scenario, right?)

So you create your user manager class that does a GET request to update some fields.

Basically, you ask your backend for information on the a player ID. With that new information, you update your UI, gameplay elements and so on.

Here's a simplified code snippet that does this update:

public class UserDataProvider
{
private string UrlUserInfo
{
get { return $"https://mygame.api/user/{_userData.userId}"; }
}
UserDataProvider(string userId)
{
_userData = new UserData(userId);
}
void Start()
{
CoroutineManager.StartCoroutine(RefreshUserInfo());
}
IEnumerator RefreshUserInfo()
{
var request = UnityWebRequest.Get(UrlUserInfo);
yield return request.SendWebRequest();
_userData.name = ParseJson(request.downloadHandler.text, "name");
// ...
}
}
public class UserDataProvider { private string UrlUserInfo { get { return $"https://mygame.api/user/{_userData.userId}"; } } UserDataProvider(string userId) { _userData = new UserData(userId); } void Start() { CoroutineManager.StartCoroutine(RefreshUserInfo()); } IEnumerator RefreshUserInfo() { var request = UnityWebRequest.Get(UrlUserInfo); yield return request.SendWebRequest(); _userData.name = ParseJson(request.downloadHandler.text, "name"); // ... } }
public class UserDataProvider
{
  private string UrlUserInfo
  {
    get { return $"https://mygame.api/user/{_userData.userId}"; }
  }

  UserDataProvider(string userId)
  {
    _userData = new UserData(userId); 
  }

  void Start()
  {
    CoroutineManager.StartCoroutine(RefreshUserInfo()); 
  }

  IEnumerator RefreshUserInfo()
  {
    var request = UnityWebRequest.Get(UrlUserInfo);
    yield return request.SendWebRequest();
    _userData.name = ParseJson(request.downloadHandler.text, "name");
    // ...
  }
}

So, what's the problem with that?

You see, verbosity is my problem.

Sure, it looks quite normal if you're used to it... (I got pretty used to this code-writing style myself).

However, there's BIG room for improvement...

And today, we will be concerned with two questions:

  1. Do we really need so many curly braces?
  2. Do we really need these keywords, such as get and return?

A very standard-driven, verbosity-lover programmer will tell you that you need all of it.

But me, as a programmer who reads thousands of line of code per day, I'll buy into anything that:

  • Reduces the amount of time I spend reading code,
  • simplifies the code that I read...
  • so that I can use my time more efficiently.

And today I'm showing you the tool that will let you achieve all of this.

Level Up With Unity C# Expression-Bodied Members

Expression-bodied members is just one of these fancy terms that are easier to understand by reading code than by trying to decipher its name.

Put simply: this C# feature lets you remove verbosity when dealing with single expressions.

That means:

  • If your getter is a single expression, you can simplify it.
  • If your constructor is a single expression, you can simplify it.
  • If your function is a single expression, you can simplify it.
  • And a few more cases alike.

We gain this simplicity by skipping certain language elements (such as curly braces) and introducing the => operator.

No worries, reading actual code will make it much easier to understand.

Remember that getter and the functions?

Well, have a second look now:

private string UrlUserInfo => $"http://mygame.api/user/{_userData.userId}";
UserDataProvider(string userId) => _userData = new UserData(userId);
void Start() => StartCoroutine(RefreshUserInfo());
private string UrlUserInfo => $"http://mygame.api/user/{_userData.userId}"; UserDataProvider(string userId) => _userData = new UserData(userId); void Start() => StartCoroutine(RefreshUserInfo());
private string UrlUserInfo => $"http://mygame.api/user/{_userData.userId}";

UserDataProvider(string userId) => _userData = new UserData(userId);

void Start() => StartCoroutine(RefreshUserInfo());

By using expression-bodied members I simplified my code so that...

  • The getter is now a single line instead of 4 or even 7.
  • The constructor is now 1 line instead of 4
  • The Start function is now a single line instead of 4.

We got rid of curly braces... and the return + get keywords.

And I could go on with more examples, but you get the idea.

You can apply this technique as well to finalizers (destructors) and setters.

Here's one last example before I go:

private UserData _userData;
public UserData MyUserData
{
get => _userData;
set => _userData = value ?? _userData;
}
private UserData _userData; public UserData MyUserData { get => _userData; set => _userData = value ?? _userData; }
private UserData _userData;

public UserData MyUserData
{
  get => _userData;
  set => _userData = value ?? _userData;
}

Neat!

What's Next?

If you missed any of my other posts on Modern C# for Unity game development, you can quickly catch up here.

And if you're wondering what else you can learn today to substantially improve your game, have a look at my tutorial on improving your game memory and loading times.

Alright, talk to you soon!

~Ruben

{"email":"Email address invalid","url":"Website address invalid","required":"Required field missing"}

Rubén Torres Bonet

About the author

Born Game Developer, now ready to help you develop better games. Primary programmer on Star Trek Bridge Crew (Oculus Quest), Diamond Dash. Programmer on Time Stall, Catan Universe, Anne Frank House VR, Jelly Splash, Blackguards Definitive Edition. I also worked in minor XR experiences for HoloLens and Vive for clients such as Audi and Volkswagen.

You might also like

The Bright Side of Ray-Traced Global Illumination in Unity
>