Replies: 33 comments 12 replies
-
The correct question isn't "why not", it's "why?" Why should C# support MI? What problems does it solve that can't be solved today through composition? C# doesn't support MI because the CLR doesn't support MI. The diamond issue with methods is probably the easiest problem for the CLR and C# to solve since virtual slots can be renamed or even hidden. The bigger issue would be state, particularly if/when it should be shared between multiple instances common ancestors. With C# effectively getting traits and multiple-inheritance of behavior I'd say that any perceived need for this would be greatly diminished. |
Beta Was this translation helpful? Give feedback.
-
Could you please elaborate on that? I often see this argument but I could never quite grasp what it means. As to the proposal, I don't think it's worth it. I was in the minority of people who were happy with Default Interfaces but I don't think we need to go further than that and even Default Interfaces turned out to be quite a complex feature. |
Beta Was this translation helpful? Give feedback.
-
When you inherit from a class you inherit all of its fields, and all of the fields of its ancestors as well. When you bring multiple-inheritance into the mix all you end up inheriting the fields of all of the base classes and their ancestors. But what happens if you inherit from two classes that share the same ancestor? Do they each have their own copy of the fields from the ancestor class, or do they share those fields?
Even with the baseline functionality it enables support for traits as each interface can have the default logic baked in. I'd suspect that |
Beta Was this translation helpful? Give feedback.
-
@HaloFour |
Beta Was this translation helpful? Give feedback.
-
The default interface implementation feature permits multiple inheritance without the problems associated with multiple inheritance of state. |
Beta Was this translation helpful? Give feedback.
-
@gafter: Such as a property that needs access to a state variable ;) To be fair, the "Why not" sounds like bullshit. The better question is: Why interfaces ? If C# would properly support multiple inheritance, you wouldn't need interfaces, and you wouldn't need interface-default-methods... To quote George Bernhard Shaw
All you would need is composition variable, e.g.:
Then you can use select and rename directives in the cases where there is a name-collision , and for all where there is no collision, you don't need select-and-rename. Doesn't sound so difficult. |
Beta Was this translation helpful? Give feedback.
-
How about using code generator for stateful mixins. For instance, I implemented a code generator for that purpose. |
Beta Was this translation helpful? Give feedback.
-
@ufcpp: Yea, now automate the mixin, call it inheritance, and it's done. |
Beta Was this translation helpful? Give feedback.
-
No. "needing access to state" isn't the problem. It is the multiple inheritance of the state itself that is the root of most problems cited with multiple inheritance.
No, programmers do not require that their problems be solved by a particular language construct. They require that their problem be solved by some language construct. |
Beta Was this translation helpful? Give feedback.
-
Don't tell me (or anybody else) what I'm supposed to want or don't want.
Which isn't really a problem if you implement MI through composition and renameable proxy-methods. |
Beta Was this translation helpful? Give feedback.
-
You're free to fork and design the language in your own image. |
Beta Was this translation helpful? Give feedback.
-
@HaloFour: Would like to, but hardly have the time to write these comments, let alone fork C#. |
Beta Was this translation helpful? Give feedback.
-
The should is your opinion. It can only turn into an expectation if you can convince the right people to take up your cause, by convincing them that MI is worth de-prioritizing other features. I for one (not that I am "the right people") haven't been convinced that MI is even a positive feature, worth implementing if there was no other work left to do. |
Beta Was this translation helpful? Give feedback.
-
OK, I give up - obviously, arrow properties and default-interface implementations are more important than MI ... Uncle Bob has a good read here: |
Beta Was this translation helpful? Give feedback.
-
Oh, one random blog post. I'm convinced. It's not like anybody ever wrote about there being problems with MI. |
Beta Was this translation helpful? Give feedback.
-
@gafter: Haha, no I certainly don't believe that, and no, didn't know. And OK - yes, if a complete platform overhaul is financially out of the question, then so is MI. However, that probably means that in the future, I'm gonna forgo any kind of inheritance that doesn't involve an abstract class, and just use composition with abstract classes instead, as everything else doesn't make much sense (IMHO). Which will then look something like this:
DI: Because if I wanted to do this with interfaces and later extend them, which requires interface-defaults if compilation isn't to be broken - I'd still need to share the connection string, and other things - not that an evil plugin-author couldn't access it by reflection anyway. |
Beta Was this translation helpful? Give feedback.
-
@VisualMelon As part of the Default Implementations feature, you're gonna be allowed to specify an access modifier on interface members, so that would solve your visibility complaint. |
Beta Was this translation helpful? Give feedback.
-
@Joe4evr thanks, I keep forgetting that (terribly important!) detail. |
Beta Was this translation helpful? Give feedback.
-
@Joe4evr That doesn't help. Private members need an implementation (You can try in the sharplab sample by yourself. It doesn't compile). @VisualMelon is right with leaves the list of observers public. The best you could do is explicit implement |
Beta Was this translation helpful? Give feedback.
-
@MaStr11 aye, it's still not ideal, but it isn't nearly as bad (only the implementer has to worry about it, it doesn't escape to the consumer) |
Beta Was this translation helpful? Give feedback.
-
Yes, but |
Beta Was this translation helpful? Give feedback.
-
Beta Was this translation helpful? Give feedback.
-
From what I can see that's not decided yet:
The current implementation gives an |
Beta Was this translation helpful? Give feedback.
-
Huh? I come from a strong Pascal background and I've never heard of this. A bit of Googling shows it's a very obscure technique for dealing with poor practice in coding, but it has nothing to do with multiple inheritance (a class having more than one direct parent class), which no Pascal variant I'm familiar with supports. |
Beta Was this translation helpful? Give feedback.
-
Regarding the diamond problem, couldn't this be solved by checking the order of declaration of superclasses and/or explicit declarations? eg. public abstract class Creature
{
public abstract void Think();
}
public class Animal : Creature
{
public override void Think()
{
throw new NotSupportedException();
}
}
public class SentientBeing : Creature
{
public override void Think()
{
Console.WriteLine("hmm");
}
}
public class Human : SentientBeing, Animal
{
// Human.Think() uses the SentientBeing implementation because SentientBeing is declared first in the inheritance list
}
public class Alien : Animal, SentientBeing
{
// explicitly declare which implementation we are using
public override void Think() : SentientBeing;
} |
Beta Was this translation helpful? Give feedback.
-
@ekolis Adding a conflicting method to the first class would cause a breaking change. |
Beta Was this translation helpful? Give feedback.
-
Beta Was this translation helpful? Give feedback.
-
I need it |
Beta Was this translation helpful? Give feedback.
-
C# supports multiple inheritance in interfaces. |
Beta Was this translation helpful? Give feedback.
-
In case anybody finds it useful, check out my composition SG |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
Perl supports multiple inheritance ("C3 linearization").
Python supports multiple inheritance ("C3 linearization").
Common Lisp supports multiple inheritance.
Pascal supports muliple inheritance ("last man standing").
OCaml supports multiple inheritance.
Tcl allows multiple inheritance (C3 linearization).
C++ supports multiple inheritance.
Why not C# ?
In Eiffel, the ancestors' features are chosen explicitly with select and rename directives. This allows the features of the base class to be shared between its descendants or to give each of them a separate copy of the base class.
Go prevents the diamond problem at compile time. If a structure D embeds two structures B and C which both have a method F(), thus satisfying an interface A, the compiler will complain about an "ambiguous selector" if D.F() is called, or if an instance of D is assigned to a variable of type A. B and C's methods can be called explicitly with D.B.F() or D.C.F().
Why not just use composition, and automagically add proxy methods/properties on the object, with select and rename directives in case of name collision ?
Usage Example:
Multiple inheritance from same class
Beta Was this translation helpful? Give feedback.
All reactions