Mocking C-sharp



If C# isn't your first language, it's got a certain "what is wrong with these people" quality. Sure, Java, Python, Scala have some funny choices, but the philosophy makes sense. With C# it feels like over at microsoft, whenever a manager gives 2-months notice they get moved over to the C# team to make some changes on their way out.

Let's just flat-out make fun of C# internet culture (I'm pretty sure most working C# coders are tolerating it, unlike the bloggers who gush).

They don't know what an interface is

The problem is that C# borrows the interface keyword from Java. This blocks all understanding that an interface is an abstract concept. They're never heard of making a class by first designing a public interface as a contract with users: I provide the functions you need, and you don't ask me how they work. To them, an interface is anything with interface written in front of it.

They have no concept of encapsulation

This is obvious, since interfaces and encapsulation go together. The funny part is, they've heard of encapsulation and have a crazy idea of how it works: make all member variables private, but completely expose them using getters/setters. Here's an "encapsulated" C# Point class, using properties (they love those things). In every way it's the same as public x and y:

class Point {
  private int _x, _y;
  public int x { get { return _x; } set { _x=value; } }
  public int y { get { return _y; } set { _y=value; } }

They'll beam with joy that Point is now encapsulated. But in this case, no real harm was done. The real problem is when they have a class that really needs private variables. They'll fully expose them with do-nothing setters/getters. It never occurs to them to design the interface first, then hide the private variables, since they "know" classes aren't interfaces.

What is their problem with plain-old-data classes?

This is the reverse of the previous issue. They regard public variables as sneaky Bolsheviks. Show an internet C# coder a simple class Point { public int x,y; } and they'll fix it for you by converting to do-nothing getter and setters.

Automatic getter/setters

What if the people using your language have a fetish which makes the program worse in every way? For example, replacing perfectly good public variables with useless get/set functions. Provide a short-cut! Here's the "improved" Point class using the automatic properties feature:

class Point {
  // no private vars. Each function below makes a hidden one
  int x { get; set; } // special short-cut. x is still a pair of fumctions
  int y { get; set; }

These can't be expanded and have no options. If you later want a real getter or setter, you'll need to rip these out for real ones, and explicitly declare any private vars.

Now's a good time to explain how the "everything must be a property" style came about, which is even funnier. At one point the C# linker was bugged so that it couldn't tell when you converted a variable into a property. Client code using p1.x should seamlessly adapt from public x to properties x. That's actually the purpose of properties. But the bug causes it not to recompile and attempt to read p1.x directly as a variable, even though it's now a function call.

They don't understand call-by-reference

At one point the microsoft C# site had this bit of nonsense: "reference variables are always passed by reference". But reference variables are pointers, and we've all seen the standard "pointer by/not-by reference" example. How could the intern have made that mistake?

The problem is learning reference types early. C# started life as a copy of Java, so was locked into describing most variables as References. They learn that first and use it often. When they finally hear call-by-reference, they can't think of a reference as anything else.

They've also already passed classes to functions which modify them. They've never had to learn that parameters are merely copies. Your basic C# coder thinks pass-by-reference is an obscure hack for the few times you need to change an integer using a function (an int? Why isn't it in a class)?

They really don't understand call-by-reference

As we know, call-by-ref has two common forms: parameters as output-only, or as "in-out" -- the ones you may wish to adjust. C# formalized this. They call output-only parms out, then strangely, call inout parms ref. This is somewhat clever since it allows them to enforce different error messages.

But this means C# coders think those are two completely different rules. They don't understand that an output parameter is using pass-by-reference as the mechanism.

pointers vs. owners

In languages with reference types you write Cat c1 = new Cat(); and think of c1 as a cat. Then you write Cat activeCat = c1; and think of it as a pointer to a Cat. A typical C# coder never thinks much about how both are declared the same way.

But at some point they'll have: Cat[] A=new Cat[10]; and will have to stop to think whether it's an array of Cats or of Cat pointers. Except they don't have any language like that. They've always just intuited it, and are stuck now, with a vague sense of unease.

They cannot settle on terms for function pointers and anonymous functions

C# originally decided that a delegate was an anonymous function. For example: f1 = delegate(int x, y) { return x+y; }. To make the syntax more intuitive, they re-used the same keyword to create function pointer types: delegate void intCombiner(int, int); created a new type, intCombiner, which can be used to declare a variable.

They later changed anon functions to work the way everyone else does it: intCombiner f1=(x,y)=>{ return x+y; }. They're interchangeable with the old way, but since the syntax was different they called them lambda functions. They officially called the old way: anonymous functions, even through the new way makes the same things. The term delegate now meant only a function type.

They then realized there should be a way to directly specify function pointer types, so added shortcuts, eliminating the need for the term delegate. Now it's just Func<int,int,int> f1;. The word delegate was already sliding into meaning a variable rather than a type, and this sealed it. So now, "delegate" in C# has its 3rd meaning: a variable.

But for functions returning nothing, Func is broken -- void isn't a type so Func<int,int,void> isn't legal. We need to invent: Action<int,int> f1;. We now, unofficially, say that a "delegate" type is an Action.

It's almost fun to read the official docs and watch them flip around using every term with every old meaning.

Structs are considered an advanced topic

By this I mean Point p1; p1.x=6; is difficult to explain in a normal C# textbook, and is discouraged. Most languages with Reference Types make it so everything with fields or []'s goes on the heap. Nice and simple. C# added "value-type classes", using the word struct merely as a speed feature. You can't have pointers to them, which also means no virtual functions, so they're regarded as inferior classes.

And we can't change the contents of structs we pass to a function. We've got to use the crazy call-by-reference trick. Those things really are an advanced feature!

New isn't new

As we know, the new keyword allocates space on the stack. Some languages using garbage collection use an implicit new: c1 = Cat(); allocates a new Cat. But C# wants you to be aware, so makes you type out new Cat().

Structs are value types, which can be assigned through constructors. You'd think they'd want structDog d1 = structDog(); to visibly not be using new, reminding you of this. But no. structDog d1 = new structDog(); is required, even though there's no allocation going on.

This is because structs, as we've seen, are an advanced topic. Many people working with them haven't learned them yet. The missing new would be confusing. The end result: new is extra verbiage, and deliberately confusing.

They can't follow their own rules about properties

The point of properties is creating virtual variables in a nicer way than getter/setter functions. The angles is in degrees, but p1.radians=5 works perfectly and is nicer than p.setRadians(5). When something acts more like a function than a variable, use a function. Even the C# manual tells you that.

But C# coders love properties and can't resist using them for more complex operations. When you debug code with these properties, they look like simple assignments. You don't suspect r1.lowerLeft=5; is a property changing several other variables. You test every function, but not that one. Your eyes glide right past it every time until you mouse-over and see Property in the tool tip. If you'd written it like a normal person: r1.setLowerLeft(5); you'd have checked it right away.



Comments. or email