What's new in C# 7.3?

Akos Nagy
May 14, 2018

C# 7.3 came out not long ago. I just had the time to do the update, so I thought I would do a post on it. There are a lot of other posts around about the same topic, but whatever. At least I can present this from my point of view :)

New generic type constraints

There are two (actually three, but wait for that a little) generic type constraints available in C# 7.3: where T:Enum and where T:Delegate. These are nice :) I have written a lot of code dealing with enums (doing some magic with the type to get the string values or conversions or whatever) and I could never really get a generic type constraint to allow only enums (that's because it wasn't possible). I mostly added struct and IConvertible and everything else I could think of. So the enum part is kind of awesome. I'm not really sure about the delegate part, but I guess that's cool too.

There is another constraint introduced to the language: where T:unmanaged. This will allow you to specify the type arguments as something allocated with stackalloc for example. While most of us don't really use this, I can see how this binds to the "reference semantics with value types" featureset of C# 7.2. Something with the unmanaged constraint probably will be a good target for conversion into Span<T>.

Expression variables in initializers

This is somewhat of a misnomer, so here are a couple of examples that you couldn't do before but now you can thanks to this feature :)

public class B
{

  private int value = int.TryParse("1", out var i) ? i : 0;
  
  public B(int v) { }
  public B(string s) : this(int.TryParse(s, out var i) ? i : 0) {  }
 
  public void Test()
  {
     var strings = new string[1];
     var r = from s in strings select int.TryParse(s, out var i);
  }
}

Basically there were a couple of places where you couldn't use out variable declartions (feature of C# 7) before, but now you can, namely:

  • Passing arguments to the base or an overloaded constuctor
  • Field initializers (and transitively property initializer)
  • LInQ queries

I don't know how useful these will be (I have managed so far without them), but they are definitely cool :) Also, the feature says something about pattern matching in the same context, but I refuse to use or popularize that in any way :)

== and != on tuples

Tuples (again, a new feature of C# 7) now support equality comparision with the respective operators. This is something quite intuitive I guess, but it's worth checking out the LDM repo for the proposal, in case you've ever wondered "why can't they just implement stuff" :)

Reassigning value of a ref parameter

This will come in handy in some cases I guess (and again a feature for "reference semantics with value types"). If you have a ref parameter, for example, now you can just get the value from the reference and assign it to a local variable:

private void DoSomething(ref int parameter)
{    
    var local1 = ref parameter; // this will make local1 the same reference as parameter    
    var local2 = parameter; // this will copy the value from parameter into a new memory address for local2
}

Applying attributes to fields of auto-properties

How many times have you wanted to use the [NonSerialized] attribute, but couldn't, because you had auto-properties? Well, now you're problem is solved:

[Serializable]
public class MyClass 
{
    [field: NonSerialized]
    public string MyValue { get; set; }
}

A couple things that I would like to point out though. I understand how this is a cool feature, but honestly, I can't think any other situation except for the one described above for this. And let's be honest, we don't really use those old formatters anymore. We use Json.NET, maybe DataContractSerializer or XmlSerializer and we use some other components if we have special protocol requirement. But BinaryFormatter and SoapFormatter? Not really. I think it would have been easier to just allow the [NonSerialized] for propreties and maybe amend the code of the existing formatters...

Pattern based fixed statements

This is something that most of us will never use, but again, a very nice example of how C# is evolving into the direction of "reference semantics with value types". See the LDM discussion for more details.

Permit indexing fixed fields in movable contexts without pinning

I'm not even going into this one. "Reference semantics with value types", for those who do these types of things. Here's the LDM discussion.

And of course there were a couple of bugfixes and they improved overload resolution, like in almost every version from C# 6.

Closing thoughts

So that's that. C# 7.3 was again a point release with some important and not so important bits. I really like the new generic constraints and the tuple comparision. And it's also worth noting how Microsoft is still building the "reference semantics with value types" featureset. We have seen some of that before starting with C# 7, and then C# 7.2 and Span<T>, but I don't think these were the last of it. I do wonder what their endgame is...

Akos Nagy
Posted in C#