See Sharp

Introduction

In order to see sharp, we eat carrots! Unfortunately tho, that’s now how we C#. C# is a language brought to us by Microsoft in an attempt to beat Java (I think?). Since the dark ages, I misconceived C# as a Java close that didn’t really bring anything new to the table … I’m severely mistaken.

I guess the main reason I am writing this is because our old friend Jim kept telling me how he wrote setters and getters in C# the “Java way”, by defining the set & get methods for private properties. Even tho that isn’t a bad practice, he was distressed about how he missed the getter and setter syntax C# has. All you need to do is read more C# code! Or, read this post.

So yeah, I guess this is a good C# crash course for those of us jumping head first into Unity … Everytime I remember Unity uses C#, and an old version even, it makes me just so frustrated and want to rant for hours about how unfortunate that decision is. Let’s just forget that for now, and focus on C#.

Programming Carrots

Getters and Setters

Well, let’s get this one out of the way already. C# allows developers to easily override a property’s getter and setter behavior using a very concise syntax that doesn’t involve defining new methods:

class Test {

    public string firstName { get; private set; }
    public string lastName { get; private set; }

    public string fullName {
        get {
            return firstName + " " + lastName;
        }
        set {
            var components = value.split(" ")
            firstName = components[0];
            lastName = components[1];
        }
    }
}

First off, please don’t use this code. A space is by no means a good delimiter to use for splitting the first name and last name.

Now, you can probably tell that the firstName and lastName properties, even though declared public, their setters are declared private. So, they can only be changed within the Test class. This is a very cool way to quickly declare readonly properties.

As for the fullName property, it is a computed property. This means, everytime you try to access this property, you trigger the code within the get block. Also, whenever you assign a new value to this property, the set block is triggered, and that new value is available in the value variable, which is implicitly defined by the language.

Lambdas

Java didn’t have lambdas until very recently, but C# had those for a long time. Moreover, they have a really clean syntax, me likey. There is a downside, tho, and it is how the lambdas infer their types. You should either construct the lambda by explicitly defining the type (you can’t use var) or by passing it directly to an argument expecting a callback.

Here is where things get hairy. To define a lambda type in a clean way, we usually use typedef in C/C++/ObjC. C# doesn’t have that, but instead, it has delegate. Such an unfortunate keyword, but oh well. Let’s see how that works:

// this won't work, since we don't know the type of x
var lambda = x => return x + 1;
// first declare the "function type"
delegate int CustomCallback(int x);
// now, we can define a lambda according to the signature above
CustomCallback lambda = x => return x + 1;

Just a quick tip, here are different ways to declare a lambda:

// pass a block of code, must terminate statements with ";"
CustomCallback lambda = (x) => {
    var y = x + 1;
    return y * 2;
};

// simple and concise
// no need for ";" at the end
// no need for a return call
CustomCallback lambda = x => x + 1;
CustomCallback lambda = (int x) => x + 1;

Events

This one is a bit weird, but definitely unique to C#. Events. Another unfortunate keyword reservation event.

Events basically help you simplify the observer pattern implementation, or even the reactor pattern. Instead of writing a data structure to hold the observers, then adding custom methods to add and remove observers, and finally iterating over the observers to trigger an event, just use event.

class GlobalEvents {
    // this is the delegate declaration we saw earlier
    // the event handler will be called for every new X value
    public delegate void EventHandler(int newX);
    public static event EventHandler OnXUpdate;
}

That’s it! We first defined the signature of the callback handlers we expect, and then declared a static event variable which we can register to. Let’s now use it:

// add a handler that will print X
// we define so we can later remove it
GlobalEvents.EventHandler handler = (x) => Console.WriteLine("x: " + x);
GlobalEvents.OnXUpdate += handler;

// somewhere, when x gets updated and we want to send an event
if (GlobalEvents.OnXUpdate != null) {
    GlobalEvents.OnXUpdate(newX);
}

// when we decide to remove it
GlobalEvents.OnXUpdate -= handler;

So, in this case, we simply registered a lambda function to print the value of x using the += operator. By adding the handler, OnXUpdate event is no longer null, and actually has handlers. So, when we later decide to invoke it, it will trigger all the callbacks with the newX value. And finally, when we are done, we use the -= operator to do the cleanup.

Constructors

This one is a quick win. Instead of bothering with repeatedly initializing an object by setting various properties, you can simply initialize the parameters using some sort of initialization block:

// mendokusai
var a = new A();
a.x = 1;
a.y = 2;

// yatta!
var a = new A() {
    x = 1,
    y = 2
};

More?

I am missing some important C# features, especially string interpolation using the $, but that’s just because Unity doesn’t support it :( For the curious, I mean this is valid C# code (outside unity):

var obj = new Object();
Console.WriteLine($"object: {obj.ToString()}");

Conclusion

Onto the OSS we march! Please don’t use the Unity forums nor packages as a source for learning C#, because they are (unfortunately) really poorly written. Most packages, even the most renowned animation libraries, have absolutely horrible code and practices (sorry to say, but it’s true). Instead, divert your eyes to Github, and tho shall see the light.