Skip to content

Instantly share code, notes, and snippets.

@marbel82
Last active March 9, 2020 09:27
Show Gist options
  • Save marbel82/3a1320a17b0b1b945a59f9f6edb9afd7 to your computer and use it in GitHub Desktop.
Save marbel82/3a1320a17b0b1b945a59f9f6edb9afd7 to your computer and use it in GitHub Desktop.
Can I implement Traits with C#8?

Can I implement Traits with C#8?

    public interface IInterface1
    {
        public void WhoAmI()
        {
            Trace.WriteLine("I am IInterface1");
        }
    }

    public interface IInterface2FromI1 : IInterface1
    {
        public void WhoAmI() // Warning CS0108 'IInterface2FromI1.WhoAmI()' hides inherited member 'IInterface1.WhoAmI()'. Use the new keyword if hiding was intended.
        {
            Trace.WriteLine("I am IInterface2FromI1");
        }
    }

    public class Class1FromI1 : IInterface1
    {
        public virtual void WhoAmI()
        {
            Trace.WriteLine("I am Class1FromI1");
        }
    }

    public class Class2FromI2I1 : IInterface2FromI1
    {
        public virtual void WhoAmI()
        {
            Trace.WriteLine("I am Class2FromI2I1");
        }
    }

    public class Class3FromC1I1 : Class1FromI1
    {
        public override void WhoAmI()
        {
            Trace.WriteLine("I am Class3FromC1I1");
        }
    }

    public class Class4FromC2I2I1 : Class2FromI2I1
    {
        public override void WhoAmI()
        {
            Trace.WriteLine("I am Class4FromC2I2I1");
        }
    }

    public class EmptyClass5FromI1 : IInterface1
    {
    }

    public class EmptyClass6FromI2I1 : IInterface2FromI1
    {
    }

    public void Test()
    {
        IInterface1 i1c1 = new Class1FromI1();
        IInterface1 i1c2 = new Class2FromI2I1();
        IInterface1 i1c3 = new Class3FromC1I1();
        IInterface1 i1c4 = new Class4FromC2I2I1();
        IInterface1 i1c5 = new EmptyClass5FromI1();
        IInterface1 i1c6 = new EmptyClass6FromI2I1();

        i1c1.WhoAmI(); // "I am Class1FromI1"      🗸
        i1c2.WhoAmI(); // "I am Class2FromI2I1"    🗸 
        i1c3.WhoAmI(); // "I am Class3FromC1I1"    🗸
        i1c4.WhoAmI(); // "I am Class4FromC2I2I1"  🗸
        i1c5.WhoAmI(); // "I am IInterface1"       🗸
        i1c6.WhoAmI(); // "I am IInterface1"       ! BAD

        IInterface2FromI1 i2c2 = new Class2FromI2I1();
        IInterface2FromI1 i2c4 = new Class4FromC2I2I1();
        IInterface2FromI1 i2c6 = new EmptyClass6FromI2I1();

        i2c2.WhoAmI(); // "I am Class2FromI2I1"     🗸
        i2c4.WhoAmI(); // "I am Class4FromC2I2I1"   🗸
        i2c6.WhoAmI(); // "I am IInterface2FromI1"  🗸

        EmptyClass5FromI1 ec5 = new EmptyClass5FromI1();
        //ec5.WhoAmI(); // Compiler Error CS1061  'EmptyClass5FromI1' does not contain a definition for 'WhoAmI' ...
        EmptyClass6FromI2I1 ec6 = new EmptyClass6FromI2I1();
        //ec6.WhoAmI(); // Compiler Error CS1061  'EmptyClass6FromI2I1' does not contain a definition for 'WhoAmI' ...
    }

After a few tests I will say... NO. It doesn't support base call polymorphism.

Adam Furmanek found (implemented) a workaround: Traits in C# Part 1 — Basic implementation with Fody

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment