Fun thought experiment, indeed. But has some limitations as well.
What if you need some data for your Traits? Where will the data be accessable? CanRoll could have properties, like Velocity or Acceleration. However, than the ITrait<T> interface is no marker interface anymore. To access this data you'll need a "T Value" property in ITrait. Hence, the traited class would need a Value-property per Trait.
The pseudo traits could have name collisions as well. What if you implement "public static void Roll(this ITrait<CanRickRoll> roller)" and assign ITrait<CanRickRoll> on Ball? What does "ball.Roll();" do?
Using this pseudo trait pattern would require to keep this limitations in mind. The default interface sure have their own set of limitations. But they become standard for all code bases of C#8.0 and above, so all developer can align themselves to this specific limitations and learn to deal with it. Integrating the pseudo trait pattern into a code base of C#8.0 and above would consequetly mean to potentially deal with limitations of default interfaces and the pseudo trait pattern.
EDIT: Manually escaped < and >
We're a place where coders share, stay up-to-date and grow their careers.
We strive for transparency and don't collect excess data.