The Evolution of the C# Language

The objective of this study is to describe how a language like C# evolves over time and all the management that it implies and to see how the different ideas and proposals are discussed and organized for future language releases.

Currently, C# is the most common language in the .Net technology sphere and, as with any other technology, it constantly changes. The latest stable specification is 8.0, used along with .NET Core 3.1.

Since Microsoft made a change to embrace multiplatform and open source approaches to many of its products, now we can see and even get involved in the C# language evolution (or in any other product that previously was exclusively private to Microsoft). See the GitHub account where all this happens HERE!

I will give you an idea on how this evolution happens. It is interesting to realize that many of them have been discussed for so many years, and for different reasons (compatibility, other components like the CLR not aligned,…) they are postponed in every release.

Proposals management and discussion

All the proposals for the C# language evolution starts with an analysis of all the ideas provided from different sources, both internal to Microsoft and external. It is possible for you to submit your own proposals to the C# language design team following a template, as well as a new issue. It generally generates a discussion where the idea is promoted or rejected. 

Those ideas labeled as proposal champions then continue with a design process and an implementation until it is delivered for an upcoming release. Other ideas are simply rejected or inactive if they are not prioritized, or if it is the case, go to the design review phase to be included in a future version release.

All this process can be followed from the csharplang GitHib project. You could implement a similar way of work for any of your projects, considering that you should create a channel to receive all the proposals and ideas and appoint a team to organize, prioritize and analyse all of them.

The discussion meetings usually follow the same agenda. Different topics are treated and a conclusion is obtained. Here you can find a recent sample:

               C# Language Design for April 8, 2020

               Agenda

  1. e is dynamic pure null check

               Discussion

  1. e is dynamic pure null check

               We warn that doing e is dynamic is equivalent to e is object, but e is object is a pure null check, while e is dynamic is not. Should we make is dynamic a pure null check for consistency?

             Conclusion

              Yes.

As for today, there are more than 1900 items registered that are in different stages. Since it is impossible to analyze all of them and most probably, they would have changed by the time you read this, I just selected a couple of them to give a hint on what the future C# language releases will bring to us (normally, a C# 9.0 version) and describe what kind of ideas are discussed in this process.

These are two of the most discussed ideas and selected for C# releases:

  • Default interface methods
  • Simplified parameter null validation

Default interface methods

This language feature will provide to C# the possibility to define a default implementation for an interface method. One of the main reasons for implementing it is that Java or Swift languages already have this feature so the API interoperability with those platforms is better. Also, a programmer can add those methods without breaking compatibility with implementations of the interface.

Of course, a class implementing the interface now is not required to fulfill this method. 

Since the class is not inheriting the interface methods (and this won’t change), a call to a default method defined in an interface will not compile. Also, a default method cannot have instances, like fields or auto-properties.

By default, these members are virtual and can be overwritten in the interface implementations. In case there is interface inheritance, it is also possible to provide a default method override in child interfaces.

A programmer can alter the modifier to abstract whenever a specific class implementation is needed for the default method.

The simplest way to define it is with a method body inside the interface:

interface ISomeInterface
{
    void Method() { doSomething(); }
}

Let’s take a look on how you could take advantage of this feature. We define a couple of simple interfaces (IVehicle and ICar) with a Car class implementing them:

interface IVehicle
{
    public decimal Weight { get; set; }
    public virtual void WriteDetails() => Console.WriteLine("Weight: " + Weight);
}
 
interface ICar : IVehicle
{
	public string FrameNumber { get; set; }
	void IVehicle.WriteDetails()
	{
       		IVehicle.WriteDetails();
		Console.WriteLine("FrameNumber: " + FrameNumber);
	}
}
 
class Car : ICar, IVehicle
{
	public decimal Weight { get; set; }
	public string FrameNumber { get; set; }
}

Now we need to write the car details, depending on if it is a car or just a vehicle, so to do it we can take advantage of the default interface methods that also allow inheritance:

void WriteDetails(IVehicle vehicle1)
{
   if (vehicle1 is ICar car)
   {
      // Write all the car details
      car.WriteDetails();
   }
   else
   {
      // Write just vehicle details
      vehicle1.WriteDetails();
   }
}

Another useful application for this feature is to add methods to our interfaces to implement any business case without breaking changes. Let’s see how we can extend the previous interfaces to include a check in case the vehicle is heavy (weight exceeds 3500):

interface IVehicle
{
    public decimal Weight { get; set; }
    public virtual void WriteDetails() => Console.WriteLine("Weight: " + Weight);
    public bool IsHeavyVehicle() => Weight >= 3500;
}

Please, note that we invoke it by using the IVehicle interface, since the Car object is not inheriting members from its interfaces:

void SomeMethod(ICar car)
{
   IVehicle vehicle = car;
 
   if (vehicle.IsHeavyVehicle())
   {
      Console.WriteLine("The vehicle is heavy");
   }
}

Simplified parameter null validation code

Every developer knows that checking for a null value in parameters can be sometimes tedious. We end up writing some kind of code like this:

void Insert(string s) {
	if (s is null)
	{	
		throw new ArgumentNullException(nameof(s));
	}
	...
}

The more nullable parameters you have, the more checks raising an exception with the parameter that is mandatory for our business, which is usually obvious.

This idea proposes to use a simplified way of doing it by adding a simple “!” to the parameter, indicating that it can be nullable and that it must be checked first.

void Insert(string s!) {
 	// s parameter is not null here
	...
}

This feature is in design review state, so we can pretty much expect it in the next C# release.

C# features and release

There is not an official release date for the next version of C# which should be version 9. Neither do we have a list of future features. But we can see a list of work in progress of what is being implemented right now with different states in this list:

Feature Branch State
Caller expression attribute caller-expression Prototype
Target-typed new target-typed-new Merged into 16.7p1
Generic attributes generic-attributes In Progress
Default in deconstruction decon-default Implemented
Relax ordering of ref and partial modifiers ref-partial In Progress
Parameter null-checking param-nullchecking In Progress
Skip locals init localsinit Merged
Lambda discard parameters master Merged
Native ints features/NativeInt Merged into 16.7p1
Attributes on local functions features/local-function-attributes Merged
Function pointers function-pointers In Progress
Pattern matching improvements features/patterns3 In progress (test)
Static lambdas features/static-lambdas In progress
Records features/records In progress
Target-typed conditional features/target-typing In Progress
Covariant Returns features/covariant-returns In Progress
Extension GetEnumerator features/extension-foreach In Progress

Anyway, I hope the due date on the GitHub page was set just for fun:

Share this post

Share on facebook
Share on google
Share on twitter
Share on linkedin
Share on pinterest
Share on email