Mixins, C#, and Roslyn

Topics: C# Language Design
Apr 18 at 2:19 PM
Hi everybody,

I've been enamored by the idea of mixins in Ruby for a long time. Now that Roslyn is come around I feel it is the perfect time to experiment with the language. I wrote a post about mixins in C# and a possible implementation route but I have no idea how to proceed. So I have a few questions.
  • Are mixins inherently a bad idea or is it a good idea?
  • Is it possible to experiment with Roslyn and implement mixins in a fork
  • On a difficulty scale of 1 to 10, where does this implementation fall?
  • Does my theoretical implementation of mixins seem feasible or is it flawed
Here is a link to my post :) http://www.khalidabuhakmeh.com/roslyn-and-the-opportunity-for-mixins-in-c

I'd love to hear from the Roslyn team and whether you have ever considered mixins as an addition to the C# language. Any comments or thoughts would be appreciated. Also great work on open sourcing Roslyn and your continued contributions to .NET :)
Apr 18 at 4:11 PM
Have you considered the brittle base class problem? Inheritance in .Net has been carefully designed so that you can add a new method to the base class and all old code will still work the same.

How would that work with your mixins? What if you use two mixins in a class and one of them changes in a way that causes a conflict with the other mixin?
Apr 18 at 5:28 PM
hi @svick,

if there is code I'm sure there will be issues :) Let me address how I think conflicts should be resolved.
  • If a mixin has a method that has the same name but different parameters than another mixin we are good (likely to occur)
  • If a mixin has a property that matches another property in another mixin with the same type then they are considered the same thing
  • If a mixin has a property with the same name but a different type, then the last Mixin takes precedence and the other has to be accessed through casting. Compiler warnings are good here.
I'm not sure if you read my post or not, but to clarify. The Mixins in this case would just be syntactic sugar over the concept of interfaces in C#, with the addition of the compiler injecting code from mixin one and two. Interfaces already have ways to resolve conflict across interfaces and developers have to make those choices anyways right? Why would a mixin be any different than those situations?
    public interface IOne
    {
        string Name { get; set; }
        void Start();
    }

    public interface ITwo
    {
        string Name { get; set; }
        void Start();
    }

    public class SkipToMyLoo : IOne, ITwo
    {
        string IOne.Name { get; set; }
        string ITwo.Name { get; set; }

        void IOne.Start()
        {
            // code from Mixin One
        }

        void ITwo.Start()
        {
            // code from Mixin two
        }
    }
So to sum up:
  • Mixins are synactic sugar around existing interface structures
  • Conflict resolution already needs to occur for interfaces, why would mixins be different?
  • I am not talking about full-on multiple inheritance :) (I promise)
Does that clear up your question (I'm sure I just created a few more) :) ?

Also thanks for humoring me ;)
Apr 18 at 10:53 PM
If a mixin has a property that matches another property in another mixin with the same type then they are considered the same thing
What if the properties are not auto-properties, and have different implementations?
If a mixin has a property with the same name but a different type, then the last Mixin takes precedence and the other has to be accessed through casting.
That's exactly the problem: an innocuous addition to one mixin can significantly change the behavior of existing code. I believe the designers of C# are trying hard to avoid that.
Interfaces already have ways to resolve conflict across interfaces and developers have to make those choices anyways right? Why would a mixin be any different than those situations?
The situation with interfaces is different: when you add something to an interface, it's always a breaking change. But when you add something to a base class, it's going to work: there can't be any conflicts between two base classes and conflicts between the base class and the derived class are solved by preserving the old behavior when the base class changes.

And your mixins behave pretty much like base classes in this regard, so I think the expectation is that adding to a mixin shouldn't be a breaking change.
Apr 19 at 4:30 PM
mixins in C# (and VB) would be a new concept so the behavior could be anything we want it to be. We should focus on the why this might be a good idea and help developers be more productive :) If mixins in .NET behaved more like interfaces than base classes I would be completely fine with that. We make trade-offs all the time, but I think mixins would be a great addition to the language, even if there are potential downfalls.
That's exactly the problem: an innocuous addition to one mixin can significantly change the behavior of existing code. I believe the designers of C# are trying hard to avoid that.
To be fair to developers to everywhere, there is always a chance you are about to break something when you are adding new code to your solution. It shouldn't be a surprise. I've seen seemingly *innocuous code take down systems many times.

Without Mixin

public interface ICar {
  void Start();
}

public interface IGpsEnabled {
  Location Track();
}

public class AudiA4 : ICar, IGpsEnabled {
  public void Start() {
    // ... code
  }
  
  public Location Track() {
    // ... code
  }
}

public class WindowsPhone : IGpsEnabled {
  public Location Track() {
    // ... same code as Audi A4
  }
}

With Mixin

public mixin GpsEnabled {
  public Location Track() {
    // code
  }
}

public abstract class Car {
  public virtual Start() {
    // code
  }
}

public class AudiA4 : Car
  include: GpsEnabled { }

public class WindowsPhone 
 include : GpsEnabled { }
Would you not prefer the second option?
Developer
Apr 20 at 7:35 PM
Your idea sounds a lot like Scala traits as implemented on the Java virtual machine. It has come up only in passing in language design discussions. I personally think it is a good idea but it hasn't bubbled anywhere near the top of the list of things we'd like to do. This is definitely something you could do in a fork of Roslyn, but it is a pretty difficult task.
Sun at 8:58 PM
Adding Mixin support to C# could be done without modifying the compiler directly. I have been working on a Visual Studio plug-in that works be generating code-behind files to compose Mixins into the Target class. So the gps example:
public class GpsEnabled {
  public Location Track() {
    // code
  }
}

public class class Car {
  public virtual Start() {
    // code
  }
}

[pMixins(Mixin = typeof(GpsEnabled))]
public partial class AudiA4 : Car{ }

[pMixins(Mixin = typeof(GpsEnabled))]
public partial class WindowsPhone {}

public class Test{
     public void Example(){
          new AudiA4().Track();
          new WindowsPhone().Track();
     }
}
You can learn more about the project at http://www.pmixins.com
Mon at 5:12 AM
Edited Mon at 5:13 AM
I think that interface delegation feature (was announced by a random guy in the internet a year ago, see "Wrapping up" there - http://damieng.com/blog/2013/12/09/probable-c-6-0-features-illustrated ) would be sufficient for implementing mixins. I. e.

interface IGpsEnabled
{
    void Track();
}

class GpsEnabledImpl : IGpsEnabled
{
    //Implementation here
}

class Car: IGpsEnabled => _tracker
{
    GpsEnabledImpl _tracker = new GpsEnabledImpl();
}


With this approach it would also be possible to pass some extra parameters to mixin's constructor.
Mon at 11:48 AM
nmgafter wrote:
I personally think it is a good idea but it hasn't bubbled anywhere near the top of the list of things we'd like to do.
Is there any chance to see that list of things? (with a big "not set in stone" disclaimer)
Developer
Mon at 5:40 PM
dsaf wrote:
Is there any chance to see that list of things? (with a big "not set in stone" disclaimer)
This is the language design notes.
Thu at 12:11 AM
In Bltoolkit there is some Code for Mixin, maybe the implementation there helps: http://www.bltoolkit.net/Default.aspx?Page=MixinAspect&NS=Doc&AspxAutoDetectCookieSupport=1