Mocking C-sharp



C# is fine. Like if your pants have some dried mud on them but you're not going anywhere fancy -- it's fine. Every language is designed with trade-offs, leaving parts that aren't so great. There's no way around that. But C# screws other things up for no reason. And there's the terrible C# internet community.

One of the steps to being a real C# programmer is taking time to make fun of it.

Annoying language features

Redundant new's

Part-I of this is a warm-up. C# is an older language and copied Java. They still uses new to allocate space. Newer languages infer it: Cat c=Cat();. That works since Cat is a reference type. We know what the line must do. C# requires the slightly longer and unecessary Cat=new Cat();. But again, that's fine -- it's an older language.

But this next thing is fully their screw-up. For their value-type version of class, named struct, they decided it needs new. It's a value-type, which can't use new, but you have to type out n,e,w. Here Cat is a class and Dog is a struct:

Cat c1; // a reference to a Cat, currently null
// create a real cat:
c1=new Cat();

Dog d1; // a struct. d1 is fully allocated on the stack

// initialize using the contructor:
d1=Dog(); // error -- makes too much sense

d1=new Dog(); //  <- aarrg! This is the line

The goal was to give structs and classes the same syntax. We can declare a Dog without even knowing what structs are. But that's stupid -- attempting to use a value-type as if it were a reference-type just makes a mess. And when C#'ers learn structs their first question is "hey, why does it use new?"

Redundant ref keyword

Here's a C# swap function:

void swap(ref int n1, ref int n2) {
  int temp=n1; n1=n2; n2=temp;

Not bad. The keyword ref is longer than C++'s &, but it's fine. Now here's a call:

swap(ref a, ref b);

Arrg! Why are those dag-nabbit ref's required? The function already knows they're being passed-by-reference. They make it look like the caller can choose normal or by-reference.

The purpose is probably safety. Call-by-ref is considered an advanced C# feature that most people won't have seen. Requiring typed-out ref's is like asking "are you sure you want this function? It uses call-by-ref you know".

A shortcut for short functions

C# has a shortcut for short functions. Short things don't need shortcuts. And it's only 1 word shorter:

double cube(double x) => x*x*x;  // the shortcut

double cube(double x) { return x*x*x; }  // normal way

This is useful because ... well, it's not.

It's for people who only use lambda functions, such as A.Find(c=>c.age<10).sortBy(c=> They aren't comfortable writing functions the normal way. It's a stupid idea since we can already write them using Func<double,double> cube = x=>x*x*x;. And if you need to write out a function, you'll eventually need a multi-line one, which "expression-bodied functions" can't do.

They can't stop redefining delegate

In C# 1.0, delegates were special typedefs. They were the only way to create a function pointer:

delegate int fct(int n);
// fct is a type for an int(int) function

fct f; // f is a function variable of type int(int)

In 2.0 delegate also became the keyword for creating an anonymous function. So now, besides a type, a delegate can be an object:

f=delegate(n) { return n*2; }

In 3.0 delegate for anonymous functions was phased out. They got a new syntax and called them lambda functions. But people still called them delegates, since the old syntax still worked and made the same thing:

f= n => n*2; // a lambda function, but also a delegate

Also in 3.0 they added an immediate way to declare function types. We no longer needed delegate-as-a-type, but could still use it. How to directly declare a function type:

Func<int,int> f = n => n*2;
// f is an int(int) function pointer

So now we've got delegate as an alternate way to define a type, or an obsolete syntax, or a general description of an anonymous function. That makes reading the docs oh so much fun.

Automatic properties

These are long ways to create something which is in every way identical to a public variable:

class A {
  public int n1; // a normal variable

  // an automatic property doing the exact same thing:
  public int n1 { get; set; }

They were created to solve an old linker bug. When you change a public variable into a property it should be seamless, but you have to remember to recompile the clients. The "fix" was to never do that -- never turn a variable into a property. Instead, start everything as a property. Clever right? After that it turned into a weird superstition. Everyone wrote every variable out as a pass-through do-nothing property:

  int _n;
  public int n { get {return _n;} set(_n=value;}}

That's tedious. Microsoft could have said "hey, it's safe to declare public variables now". Instead they created a shortcut so you can appease the god of useless properties in fewer keystrokes.

Hyper-detailed virtual functions

In C++ you have to add virtual in the base class. In Java you don't do anything at all. In C# you not only write virtual on top, you need to add override everywhere else. If you don't, that one function isn't virtual. This is so you can write a subclass, decide not to override a virtual function, and then say "my boss The Joker wants me to write a normal function with that same name".

As a bonus, same-name-but-not-an-override functions are supposed to have new in front of them. Sure, let's re-purpose a completely unrelated keyword for this.

It's to avoid a very specific oddball problem. Suppose you have a base class and users have already written subclasses. Then you add a new virtual function, in your base class, which accidentally shares a name with a normal function a user added to their subclass. The user's function would mistakenly, with no warning, become the override. But with C#'s fine-grained rules it won't.

That could happen, but hardly seems common enough to justify torturing us to avoid it.

The C# internet community

Now we're onto a different but equally annoying part of C#. Trying to look things up. Searches find the worst blogs, or the awful microsoft site. Every language has a certain amount of annoying, outspoken clowns, but C# is extra clowny

Everything is the best

The desciption of even the most minor feature starts with several paragraphs about how great it is. If C# was a hardware store and started selling yellow nails, the manual would start out explaining how this new technology allows us attach boards together. It's impossible to find out what anything actually does or why it was added.

New things are always better

The var keyword is for a very specific special case. But it's new, so naturally every example of everything uses it. It's all that way. Every example has every new feature inappropriately ram-rodded in, making them impossible to read. Especially since checking the manual simply says "they're great!"

They don't understand information hiding

The standard way of writing a C# class is to choose your internal variables and expose every single one as a property:

class Widget {
  int privateVar1 { get; set; }
  string privateVar2 { get; set; }

Their reasoning is that the sole rule for OOP is "no public variables". They don't understand the part about hiding the implementation details. They don't know that making variables private is meant to accomplish something. Their OOP begins and ends with "no public variables".

They don't know what an interface is

If you don't know what information hiding is, or course you don't understand interfaces. But C# makes it better, then worse. C# uses interface as a keyword for a fully-abstract class. This confuses C#'ers. To them, an interface means something clearly labelled "interface". Classes don't have interfaces because -- no interface keyword.

The weird thing is that they correctly understand the interface concept for the things that say interface. They understand that clients are supposed to only look at those functions, ignoring implementations. They just can't transfer that idea to writing a class.

Interfaces start with I because...?

A C# convertion is to start all interface's with a capital I. That way you can tell them apart from normal classes. But there's no reason we should care. Consider a function which clearly takes subclasses as input:

void doStuff(Animal a) {; ... a.sleep(); ... }

Animal could be a base class, or an interface. will be found by the same rules either way.

That stupid "I" prefix makes you think C# interfaces aren't fully interchangeable with abstract classes. But they are.

Structs are considered an advanced topic

For real, structs are easy. Even C# structs. They're simple value-types. But languages with reference types are taught a certain way which makes structs difficult to understand.

Firt they learn forms like Car c=new Cat;"steve";. Then that Cat cp=c; acts as a pointer. And that's enough for most things.

After that, it's difficult to explain why you'd need structs. They're only a speed trick. As to the implications of "value-type classes", C#'ers don't have the background yet. Structs are where they learn heap, stack and formal pointer theory, all at once. Effectively. structs in C# are very complicated.

If you're a native C# coder wondering how structs could ever not be complicated, here's how:
First learn ints, doubles, and strings. Then learn structs. Now you're thinking "but you need references to write a useful program". That's right. We learn the basics using simple programs, then learn how references work and we're ready to go. It takes longer to be a semi-useful programmer, but the end result is better.

They don't understand First Principles

C# programmers think of everything as it's own thing. They think while, for, do-while and foreach are different. They don't realize they're all just loops with small tweaks.

Everything is like that. They'll explain a minor change from the ground up, paragraphs and paragraphs until near the end you realize "oh, it's alternate syntax for doing X".

They don't understand call-by-reference

In C# you rarely need call-by-reference. That's because you pass around classes, changing the contents through the copied reference. That's good enough for most things. They only need call-by-reference for oddball special-cases.

But when they get to it, they already have a firm idea of what "reference" means. They've been saying reference variable and get a reference for a long time. They can't see "call-by-reference" without imagining a reference variable, which that is not. The microsoft C# site even once got it confused, saying reference variables are always passed by reference (no, that's not true).

They really don't understand call-by-reference

As we know, call-by-ref has two common forms: parameters as input-output, or as output-only. C# formalizes this with keywords ref and out. They get slightly different rules -- it's actually quite clever. For example out variables don't need to be initialized and can't be read from.

C#'ers learn these as 2 similar but unrelated features. They don't understand the underlying mechanism is identical -- a hard link back to an L-value.

pointers vs. owners

This is just a general complaint about any language using refertnce types. You can't tell the difference between an owner and a reference. In C++ you write Cat C[10] for an array of 10 Cats. You clearly own them, since they're in you. An array of 10 links to other cats is Cat* C[10]. These are clearly links to cats we don't own, otherwise we wouldn't have needed to turn them into pointers.

Meanwhile in C# everything is Cat[] C=new Cat[10];. We can't tell if it's intended to own 10 Cats, or merely link to someone else's. And since there's no syntax for it, it's difficult to talk to C# coders about the difference.

Overly complex properties

The point of properties is creating virtual variables in a nicer way than getter/setter functions. We may store the angle in degrees, but offer p1.radians=5 as a property, nicer than the alternative p1.setRadians(5).

But C# coders love properties and can't resist using them for more complex operations that always cause problems. They'll have r1.lowerLeft=5; as a property changing several other variables. When we get a bug it takes extra-long to realize "oh, that's a function call". If you'd write it like a normal person: r1.setLowerLeft(5); we've have fewer problems.



Comments. or email