Posts /

Void-Free Style in C# 7.0

22 Apr 2017

Fans of functional programming and/or strong typing certainly know unit: tuple with zero elements, type () that only posses the single value (). C# 7.0 now has it too, albeit with a slightly ugly name: ValueTuple.

Let me explain.

C# has void keyword and it’s not a good thing. It creates an artificial asymmetry between methods that return something and methods that do not return anything. From this decision follows the necessity to distinguish between Func<> and Action<>.

In Haskell, you have type () and it’s what it looks like: the empty tuple. This type has the single value (), so when you are returning it, you are not conveying any information. (Well, up to the fact that you are returning, but this distinction between unit and bottom is not important for us now.) It’s a good replacement for a special keyword like void, because it fits well into another concept (of tuples) anyway.

If we had () in C#, we would not write Action<int>, but Func<int, ()> – we would abolish Action completely. In a similar vein, we would be able to use ConcurrentDictionary like ConcurrentDictionary<string, ()>, i.e. as a non-existent ConcurrentHashSet<string>.

We know that there are differences between System.Tuple<T1, T2, ...> and System.ValueTuple<T1, T2, ...>: the most important one being that the old Tuple is a reference type and the new ValueTuple is a value type.

Did you notice though that there is System.ValueTuple without generic arguments? System.Tuple is just a static shorthand for creation of generic tuples using its Create method, you can’t instantiate it.

This instantiable System.ValueTuple is unit in a very real sense. It’s inhabited by the single value, so new ValueTuple().Equals(new ValueTuple()), default(ValueTuple).Equals(new ValueTuple()). Conceptually, it corresponds to Haskell’s type () as “product of empty set of types”.

Unfortunately, the language does not accept () syntax sugar for System.ValueTuple:

public () DoStuff() // <- does not compile
    // ...

    return (); // <- does not compile

This has the same meaning though – and it compiles:

public ValueTuple DoStuff()
    // ...

    return new ValueTuple();

It’s kind of nice that in this way, even beginners see the difference between “value ()” and “type ()”. That makes problems in Haskell sometimes.

It arguably looks weird though, especially given already suspicious name ValueTuple for such a fundamental thing. It’s difficult to imagine an organization that decides to opt into this style just to make the codebase slightly more consistent and nice.

Nevertheless, void-free style is from now on possible in C#. All it takes is to write an analyzer that forbids voids and Actions.

Lukáš Lánský (e-mail)
Return to the list of posts

Share: Twitter Facebook Google+