Thinking of @CaseyLiss when learning C#

Software

With potentially my last C# project at university wrapping up, I thought I'd share some "outsider" experiences with the language before bidding it farewell.

Skip this nostalgia crap

My first experience with C# was in high school. At my weird Australian International School in Singapore, a bunch of us did accelerated Software Design and Development. Unfortunately, the course should have been called Software Algorithms, as there was no officially mandated development in the silly-bus. VB had been used to demo ideas, which I translated to VB.NET at home, then made the leap to C#. It seemed oddly familiar, almost like VB.NET expressed with C syntax. I was about to learn there was far more to it!

My dad bought me The Petzoid Book at the time. I've since learned it's the Perl Camel or Ruby Pickaxe of the C# world. Even as a Mac and *nix guy now, I do like how the book flows, and many pages have been folded and spilled with coffee. Good times.

But I digress. Sitting at UTS this year, I couldn't help but smile as all this nostalgia washed over me. In some ways C# has changed markedly since I moved off Windows in the 2000s, but in other ways it was its old familiar self. In fact, it was almost… too familiar; doing Java and C# in the same semester was a recipe for confusion and misplaced syntax.

Data types

In Java and C#, Strings are reference data types. In C#, lowercase "string" is a keyword alias, so we can use both interchangeably.

string Greeting = "Nyanpasu~";
String strcopy = "Look ma, no pointers!";

Simpler data types such as int are actually structs. Remember those from C? More on those shortly.

Auto-implemented properties

An interesting, almost Ruby-esque feature is auto-implemented properties. There's insufficient for complex classes, but if you're mostly encapsulating simple properties, you can avoid all that nasty Java getter/setter boilerplate. For example:

class Character {
    private string name;
    public string Name {
       get { return name; }
       set { name = value; }
    }
}

That I had seen. Since I was gone, C# further simplified it:

class Character {
    private string name { get; set; }
    public Character(string name) {
        this.name = name;
    }
    static void main(string[] args) {
        Character ryuuji = new Character("Ryuuji");
        Console.WriteLine("Hello, {0}!", ryuuji.name);
    }
}

Brackets and evil

I like K+R C brackets, but Visual Studio defaults to newlines, and most documentation uses them. To each their own, but I feel they just add tedious scrolling. Though we can all agree they're far nicer than the hideous GNU recommendations.

C# also allows eschewing (gesundheit) brackets for single line conditional statements and loops. If you think that's bad enough, they also allow GOTO lines.

if (true)
    goto hammerspace;

Die twice, already!

enums

Compared to Java 5+, enums in C# are limited to just representing named constants. This reduces overhead, but you'll need to break out a new class for anything more.

private enum Scale {
    Tsundere,
    Yandere,
    Kuudere
};
static void main(string[] args) {
    Scale tiger = Scale.Tsundere;
    if (tiger == Scale.Tsundere) {
        Console.WriteLine("It's not like I wanted to be an example...");
    }
}

structs

One of the first questions I had when learning Java regarded all the syntax errors my structs were generating. In C#, they're still a part of the language, and are encouraged over fully blown classes for simple data structures due to their lower overhead. The primary practical difference (I can see) is they don't support inheritance.

const and readonly

By now I was starting to realise C# was a little more like C than Java, at least in some ways. My const-antly appearing friend is here, and she brought an initialise-at-runtime companion in the form of readonly:

public const OVER = 9000;
private readonly bool nice;
public Character(bool isNice) {
    nice = isNice; // daijoubu~
    OVER = 2000;   // oh no, you didn't
}

out and ref

I have mixed feelings about these. Broadly speaking, they allow you to pass value types by reference. With out, you must pass it an uninitialized variable, which must then be given a value within the function.

void Process(ref int x, out int y) {
    x = 10;
    y = 20;
}
static void main(string[] args) {
    int x = 1;
    int y;
    Characters.Process(ref x, out y)
    Console.WriteLine("x is {0}, y is {1}", x, y);
}
==> x is 10, y is 20

Namespaces

In most languages I've encountered, we declare the namespace for a class in the source head. In C#, namespaces contain the class within brackets. I can see the pros and cons for both approaches.

namespace Animu {
    class Characters {
        // put methods and attributes here, desu
    }
}

Conclusions

So, that's the end of part one. I have another post queued up with a comparison of Java and C# generics, anonymous and delegate functions, some other random pieces like coalesced nulls, sealed classes, and a brief look at reflections and Linc. No wait, Linq. Clearly I need to select my words more carefully. GET IT!?!? AAAAA… nevermind.

I don't see myself ever writing C# professionally, though I've found the trip fascinating and can see why the Casey Lisses (Casey Lissii?) of the world like the language. At the risk of alienating some of my readers here, I would prefer it to Java. Should I be cowering in a bunker somewhere now?

That said, I aspire to have more Swift and Ruby in my immediate future. And $perl, because it was my first love. Shaddup.

Author bio and support

Me!

Ruben Schade is a technical writer and infrastructure architect in Sydney, Australia who refers to himself in the third person. Hi!

The site is powered by Hugo, FreeBSD, and OpenZFS on OrionVM, everyone’s favourite bespoke cloud infrastructure provider.

If you found this post helpful or entertaining, you can shout me a coffee or send a comment. Thanks ☺️.