Default Interface Methods in C#: What Are Traits, and Why Are They Needed?

Curious to see what my fellow .Net developers/architects think of this new language feature that's been bandied about since at least early 2017, though it's now potentially slated to be included in C# 8.0. I have to admit, at first I didn't "get it" but I've been doing some serious research on my own over the past few weeks, and had an aha moment when I read the accompanying research document linked to in this page. By allowing method implementations in interfaces, this would enable "traits" in C#, which has proven itself to be a very powerful programming paradigm in other languages.

So what are traits? Traits can be thought of as something between an interface, and a mixin. Basically, it allows you to create chunks of reusable code that provide "behavior" aspects to classes, but by definition are not allowed to hold any state. We can do this now via interfaces, but it's up to the class itself to implement the behavior, thus negating the reusable portion (unless you subclass your derived interface definition). Scala has had this for years, though in that language they are used more as we currently use interfaces in C# (albeit with method implementations). Traits at their core are reusable blocks of code that can provide common qualities between related types, which serve to *enhance* the type.

In the accompanying PDF, the authors describe a process wherein they reauthored the collection classes in SmallTalk to take advantage of the traits addition to that language. It vastly simplified the class hierarchy by defining a specific set of traits that are shared amongst the various collection classes, instead of using deep object hierarchies (which can get very confusing...look no further than the Stream classes in .Net as a namespace ripe for overhaul via traits due to rampant inheritance misuse and abuse). 

How did the authors improve the collection classes in SmallTalk? What the authors did was rip out various commonalities shared between collection classes, and implemented them as traits, e.g. instead of having a SortedArray, you would just have an Array, but also define a TSortable trait. Now you could apply that trait to any collection class that needs to support sorting, instead of having something like SortedArray, SortedDictionary, SortedSet, etc. In each of those collections, you have shared (and probably duplicated) code that implements sorting in the various collections. Now, you'd just have something like an Array, Dictionary, Set, with a TSortable trait that is *shared* amongst them. It's the up to the class itself whether it needs this behavior...and it's this word, "behavior" that is core to the understanding of how traits can be used to simplify your class architecture.

In .Net, one could see this being implemented in some sort of fluent API, where you specify the type of "behaviors" you want your classes to have via .methodCall() syntax, e.g. starting with the class you need first, followed by further refinements to the behavior you need from the class via a fluent API. Something like ConcreteClass.SomeBehavior.AnotherBehavior.EvenMoreBehavior seems much more understandable than casting to other types, or newing up a ton of classes and "gluing" them together to get your desired final class implementation. This also has the added bonus of eliminating a lot of boilerplate code within your classes, instead having a class that simply holds state, and then a set of traits that define the behavior your class needs. By designing your traits correctly, you'd also end up with quite a bit of reusable code in your traits that could be used in other classes. The authors of the PDF I'll link to in the comments uses the following equation to define how your new classes would work with traits:

Class = Superclass + State + Traits + Glue (the glue is how you wire the traits together...traits cannot directly access state of classes, but *can* access them via getter/setter paradigms, which of course C# has built in via properties).

In .Net, Traits would be implemented as method definitions on interfaces, and of course you can inherit from as many interfaces as you want. Ideally, I'd love to see traits promoted to a first class citizen, but I expect there would be numerous libraries that would be released that would provide this behavior (probably via generic type parameters on the class itself, where the type parameters are constrained to the type definition of the interfaces...I've already been mulling this over in my head).

How is this better than Mixins? Mixins are injected into the class inheritance chain, whereas Traits live "beside" the hierarchy, and can be injected whenever needed. Class hierarchies are rigid, traits are fluid. Mixins provide reuse via inheritance, traits provide reuse via composition, and composition wins over inheritance in almost all scenarios as it allows for much more flexibility, as well as dynamic dispatching at runtime without the design time constraints of inheritance. Also, multiple inheritance is not allowed in most languages, so you have to further complicate your class hierarchy to get the benefit of multiple mixins. Traits can be injected (or subclassed, or override the default method implementation) wherever you need them, without cluttering up your class hierarchy.

All in all, I see this as a beautiful addition to the C# language, though they are still working through the details (e.g. should static methods be allowed? << I don't think so, and other "keyword" based discussions). Initially I was skeptical, but after reading the PDF mentioned in the body of this article, and seeing how the authors implemented it in the collection classes in SmallTalk, I was sold. Being able to inject shareable "behavior" amongst classes is a no-brainer. I hope this makes it in to a future version of C#.