-
Notifications
You must be signed in to change notification settings - Fork 4.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Proposal] Private inheritance #5270
Comments
What would happen to the members that the type doesn't "opt-in" to? What if you upcast to the parent type or interface and attempt to call those members? The type is a contract (particularly in the case of interfaces) and I would argue that you shouldn't be able to not implement the required members. Even if you could hide those members they should still be required to exist. Wouldn't your use case be better served through a proxy? |
As for "hiding" members, that is already supported through explicit interface implementation in C#. The CLR also supports a form of "explicit" overriding of virtual members where the name and accessibility of the member can be different, but C# doesn't expose this functionality. In both cases the type can be upcast and those members visible. |
Is there a good use case for this? I think composition (with a kind of yet unimplemented traits = "let inner object implement outer interface") and extension methods cover most (all?) of the use cases. |
Your proposal looks like syntactic sugar for composition, not inheritance, am I right? You want to reuse the implementation, but not the interface, plus you don't need subtyping. |
Would it also work for sealed types and structures? |
I think this would be of pretty limited use. Wrapping is common, but when you do that, you usually expose the functionality in a different way, you don't just hide some members. Because of that, I don't think this is worth having special syntax. |
I often find myself writing code like this:
Notice a pattern with the methods? Looks pretty wet.
Still, this doesn't scale particularly well if I have large interfaces and only want to exclude parts of them (repeating 20+ interface methods, even if I need one line for each, is still pretty wet). However at least for me this gets "close enough" so I wouldn't really be bothered by it. tl;dr I think that reducing boiler-plate required for composition may be easier and more worthwhile than introducing a completely new concept to tackle this problem. |
I agree, I think traits would go a long way. Basically being able to send in The only thing I don't see traits provide, is improving composition. @default0 points out an alternative syntax, that maybe together with traits would be a good combination? |
@default0 You could just inherit from |
@AdamSpeight2008: If I understand @default0 's case correctly, he wants to reuse the list functionality by composition, but only expose a subset of List<> or IList<> members. At least for me, it comes down to a lot of code for simple wrapper types. UsecasesI'm sure there are many usecases for this, but the ones that I've experienced myself or can think of are. Hide members to avoid bugsEx: Hide members to limit the exposed functionality or make the intention more clearEx: ReadOnlyCollection that according to source code also just wraps a passed in IList object. AdaptersAdapter type to connect legacy or third party code to new types. Private inheritance revisitedAfter feedback in this thread, I am now leaning towards primarily traits and possibly an improved composition syntax to meet the needs of this issue.
|
@anjdreas Jon Skeet's proposal on mixins is here (didn't find it on his blog). |
I'd like e.g. for public abstract class Stream : IDisposable, private IReadStreamAsync<byte>....`
{
public IReadStreamAsync<byte> AsReadStreamAsync()
{
if (!CanRead) __Error.ReadNotSupported();
return this;
}
} So you can do Stream readonlyStream;
IReadStreamAsync<byte> reader = readonlyStream.AsReadStreamAsync(); But would be prevented at compile time from doing Stream writeonlyStream;
IReadStreamAsync<byte> reader = (IReadStreamAsync<byte>)writeonlyStream; |
@benaadams How is that better? As far as I can tell, you're just exchanging one runtime exception ( |
@svick its better as its maintaining the contracts. You'd get a compile error if you tried to cast; so wouldn't be able to; and yes, unfortunately a runtime error for The otherway; either Or you would implement the interface which would allow the cast; but then the user of the interface wouldn't be sure it was a readable stream and calls to Which I think would be worse as its clearly violating the interfaces contract; would happen much further along the call stack; and be harder to work out why and where the non-readable readable stream came from. |
We are now taking language feature discussion on https://github.com/dotnet/csharplang for C# specific issues, https://github.com/dotnet/vblang for VB-specific features, and https://github.com/dotnet/csharplang for features that affect both languages. |
Problem
It is tedious to wrap a 3rd party type with the intent to expose only a subset of its public members, by implementing and forwarding property/method calls.
Motivation:
Proposal
Introduce a new inheritance syntax for private inheritance, which allows you to choose what members to make public, either by opt-in or opt-out, whichever is the most convenient. Similar to private inheritance in c++.
Example
Update 2015-09-27: See updated usecases in comments.
Consider the syntax purely for illustration purposes.
Private interface inheritance
Concerns
I am probably way off here and have likely missed a fundamental flaw, but I found the idea intriguing and could not find any previous discussions on the topic. Would love some feedback and thoughts from people with more insight.
Update 2015-09-18: Remove misleading comment in alternative 2.
The text was updated successfully, but these errors were encountered: