Feature Requests for C# 7.0

C# is an amazing language which get improved with every version and now .Net become portable which is even more amazing. However there are still some features I'm missing or problems I want to see solved.

Scope and Resource

IDisposable interface and using statement are problematic, I really think it is the second biggest design flaw in C# (after events, the cause of all memory leaks).

Some of the issues:

  • You can forget to dispose an object and cause memory leak or exhaust operating system resources.
  • With using keyword you unnecessarily indenting the code and make it harder to read, especially when nesting multiple using.
  • You don't get any errors with you using object that implements IDisposable without using using, this is just calling for bugs.
  • If you are writing a public library and didn't use IDisposable at the beginning and add it later you actually cause same problem as forgetting to dispose an object as in the first bullet.

So the first addition is the resource keyword which you can use at class declaration. When using the resource keyword it is like implementing IDisposable except you get a compile error if you didn't scope the instance. So what exactly is scope? first let see the how to use the resource keyword:

resource class Socket  
{
  void Dispose()
  {
    // Do something, or not...
  }
}

Actually the Dispose method is optional, because usually with resource class all resources will be released automatically because of the scope keyword.

So what is the scope keyword, when create a resource class you must scope (in golang it called defer), when you scope a resource class it will get disposed when you exit the scope. Scope can be at class level or scope level.

Let see some examples:

class resource PersistentList  
{
  // class level scope variable
  private scope AutoResetEvent loadedEvent = new AutoResetEvent();

  public void Load()
  {
     scope FileStream stream = new FileStream(FileName);

     loadedEvent.Set();
  }

  public void Save()
  {
    // If we really want we can still use Using
    using (FileStream stream = new FileStream(FileName))
    {
    }
  }  
}

So as you see we don't even need to implement the Dispose method, because all resources will be disposed automatically when the scope will exit. The important role of the resource keyword is to make sure a compilation error will happen if resource class is used without scope or using. Bottom line this saves bugs, memory leaks, writing dispose method and code is cleaner (no unnecessary indent).

Messaging

It is hard to write high performance or concurrent systems with C# and .Net, I know this from first experience, even async and await doesn't really solve the problem. The real problem is that C# and .Net doesn't encourage the right pattern for high performance systems.

Let me explain, if you read the ZeroMQ guide or familiar with NetMQ and/or ZeroMQ you know the philosophy is to never share data between threads, instead we exchange messages between threads. Sharing data between thread is slow and very complicated, usually an art only few can master.

The problem with C# is that sharing data is in the syntax of the language with lock and volatile keywords. Also the library is full with share data classes like ConcurrentBag, ConcurrentDictionary, ReaderWriterLock, ManualResetEvent and more.

Language that want to support high performance should prefer messaging over locks, golang has channels (which are like queues) and goroutines (which are cheap threads), erlang has actors, and C#? C# has BlockingCollection, only from .net 4.0, which is not enough.

First we need a way to create threads that are not really OS threads, we can do this with the various single thread TaskScheduler implementations (as NetMQ Poller is doing) but remember we want the support in the language.
The other parts is that we need a way to wait on a queue (without really blocking a thread) and on multiple queues.

Following is a suggestion:

void Main()  
{
  Channel<int> channel1 = new Channel<int>();
  Channel<int> channel2 = new Channel<int>();  
  Channel<int> channel3 = new Channel<int>();  

  // Calling a concurrent routine
  SingelQueue(channel1);
  MultipleChannels(channel2, channel3);

  // Sending to a channel
  5 => channel1;
}

concurrent void SingleQueue(Channel<int> channel)  
{
  while (channel.Open)
  {
    // Receiving from channel, this is actually not blocking the
    // thread but release it back to the thread pool, like await.
    var item <= channel; 
  }
}

concurrent void MultipleChannels(  
  Channel<int> channel1, Channel<int> channel2)
{
  while (channel.Open)
  {
    select
    {
      case var m <= channel1:
        // Do some processing
        break;
      case var m <= channel2:
        // Do some processing
        break;
    }
  }
}

Another important point is to make this extendable (which golang didn't do), so if I want to develop my custom channel (NetMQChannel for example) I can, following is a suggestion for receiving interface:

delegate void Callback(IReceiveChannel<T> channel);

interface IReceiveChannel<T>  
{
  void RegisterForCallback(Callback callback);  
  bool TryReceive(out T value);
}

So the custom channel will need to implement RegisterForCallback which will be called when message is ready to be fetched.
TryReceive, which will be called within the callback, will actually retrieve the message if it still available.

For more information take a look at libmill for C or golang channels.

Parameter-less Lambda

Today when you want to create parameter-less lambda you have to use parenthesis, which is just boilerplate and verbose, so instead of this:

() => Console.WriteLine("Hello");

I want to do this:

=> Console.WriteLine("Hello);

Syntax is cleaner and less code to write.

Multiple return value and pre-statement

In my opinion the exception usages in .net library is mostly wrong, if we actually want to write safe code almost every line of code need to be wrapped with try-catch. I much prefer the Try pattern, like with TryGetValue of dictionary.

However using the Try pattern is a little annoying, you need to remember to create a variable before calling the Try method, which is not how my brain works, when I get to the Try method I usually go up one line and declare the out variable. Also the variable is defined in an outer scope while you usually use it inside the if statement. My suggestion is to return multiple values, so instead of this:

string text;  
if (dictionary.TryGetValue("Greeting", out text))  
  Console.WriteLine(text);

We will write this:

if (var text, found = dictionary.TryGetValue("Greeting"); found)  
  Console.WriteLine(text);

The text variable is defined in the correct scope, we don't have to use the out keyword and wrote less code. I like this syntax better, although the pre-statement can look better, I'm leaving this to Microsoft.

Instant enums

Continuing the previous example, it would be much nicer if instead of checking the found boolean value we will do it like this:

if (var text, result = dictionary.TryGetValue("Greeting");  
    result == Found)
  Console.WriteLine(text);

The problem with writing a lot of enums, it is too verbose, you get a class with a lot of internal public enums, you don't know which method use which enum and you also have to think of the names for all those enums. So I would like to do it in method declaration:

// Property
public {NotStarted, Running, Disposed} Status {get; private set;}

// Method
public {Ok, QueueIsFull} Enqueue(string value);

// Method with two return values
public string, {Found, Missing} TryGetValue(string key);  

Summary

Hopefully you get the point, I didn't make it bulletproof features yet, just suggestions and way of thinking. The bottom line is clearer code, less code, more safe, less bugs and built for performance.

comments powered by Disqus