-
Notifications
You must be signed in to change notification settings - Fork 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
Champion "Covariant Return Types" (VS 16.8, .NET 5) #49
Comments
The part about support in interfaces, does this mean something like the following? public interface IFoo { }
public interface IBar
{
IFoo Get();
}
public interface IBaz : IFoo { }
public interface IQux : IBar
{
override IBaz Get(); //or would it be 'override IBaz IBar.Get();'?
} I guess it's lucky that discussions around Default Interface Implementations have pushed back a little bit on using |
I find myself wishing C# supported covariant returns very often, and often with code that isn't particularly "clever". |
Covariant returns would be very useful for typed cloning methods, preventing the need to manually create unique protected cloning methods. |
Why didn't this happen yet? |
@MohammadHamdyGhanem
Because you haven't written it yet. Seriously, there are a million "good" ideas, modifying the language is a very expensive process and the team has finite resources. Things take time. |
If I can write "it", I would rather write a new S# (Smart Sharp) language, where I do whatever I want :). Anyway, may God help the team :) |
Would this need CLR changes, or compiler changes only? |
According to linked proposal document it is purely compiler magic. It is mentioned that compiler will spit two methods instead of one. One virtual override and another who will call this override and cast result to more specific instance so nothing fancy. Though for that reason alternative mentioned in proposal SEEMS to be better for performance but that will come at the cost of ugliness in code (method duplications). I wonder if both couldnt be combined into one proposal? So compiler will produce same code to alternative but source code will look like original proposal. |
For a long time I didn't realise that the problems I had with many of my inheritance/interface heirarchies nearly always came back to this common problem - the lack of return type covariance to allow overriding methods to narrow their return types. This then leads to duplication of methods and properties to satisfy both the base and the subclass contracts, which is a whole lot of general messyness. So I am very much in favour of this proposal. |
@gafter If you think this is likely to succeed, I will go ahead. Some pointers on the process I will need to take would be helpful. @ldematte, I assume you are no longer working on this, but if you are, please let me know, and we can discuss if I can help. Also, if you've achieved anything useful so far, it would be great if I could build on that. Also @sharwell and @HaloFour were arguing on how best to implement this, and no decision seemed to be made. Should I just go for this with Method Shadowing, or do we need to finish that discussion first? |
I think this will require some (perhaps substantial) design work before the desired/best implementation techniques are decided/agreed. |
@gafter |
@YairHalberstadt That would help. It would also help to understand how this would affect any tools that consume IL, including compilers for other languages. |
Ok. I will get started on a design proposal. |
To save you a little time, fell free to recycle the work I did when I was looking at feasibility. |
https://gist.github.com/ldematte/39b9f3119a92dc058799 Are the relevant parts |
Thanks Idematte. I'll definitely use whatever I can from your work. |
Can you be more specific? What strange/unintuitive suggestions are you referring to? Thanks! |
Honestly, I can't recall. |
I have just tried it with VS2017 and it works flawlessly, proposing them as overloads (even it is just the return type changing). |
That would be great thanks!
|
https://www.dropbox.com/sh/hw0sgrae83i93lm/AAC_YXcNxjY3q70JExCoAWfOa?dl=0 There is also a draft proposal I forgot I wrote :) |
Are you sure that this is what end users need, rather than something that you C# team developers need? |
Pattern matching, especially when combined with collection pattern matching, is incredibly powerful and succinct. It can easily turn 20 lines of difficult to follow code into a simple switch expression with a few lines. I use it all the time in normal app development. |
There are lots of examples in the search |
Can the mods please delete the above discussion so we can focus on the matter at hand: |
It's also easy to find some pretty awful examples.
I'd love to see an example, but it looks like we digressed too much. Probably better to move this discussion to somewhere else. |
Does it even need to be implemented? You can achieve similar results with DIMs on interfaces. Where is the lack of this feature overly burdensome? interface IBase
{
object GetValue();
}
interface ISub : IBase
{
new string GetValue();
object IBase.GetValue() => GetValue();
}
class C : ISub
{
public string GetValue() => "Wooo";
} |
It was a huge pain with classes because you couldn't override a base abstract method and provide a more specific one with the same name. It's not an issue in interfaces. |
I think that simply auto-adding stub methods would be enough. Unlikely that changing runtime is really needed. |
@mikernet interface IBase
{
object GetValue();
}
interface ISub : IBase
{
new string GetValue();
object IBase.GetValue() => GetValue();
}
class Evil : ISub
{
public string GetValue() => "Foo";
object IBase.GetValue() => "Bar";
} |
Nope. I'm not sure. But what of it? Ultimately, certainty is not the goal. |
That was Jared. But we are often easily mistaken. |
This is possible today with source generators. If this is enough, if advise you to just implement that as you have a solution today (which could work across all version I if c#), versus waiting years for us to do it. |
@Charlieface I don't see it as hacky, it's relatively simple. I don't really see the problem, but that's just me. Even if
|
@CyrusNajmabadi gosh. I wasn't looking for _any_solution, there is a number of obvious ones. I just want this thing to be fixed finally. |
If you really want to blow minds about the whole "consistency" argument, .NET has always allowed for "explicit" overrides, C# has just never supported them. Covariant returns might have not been necessary at all if it did. 😁 |
Why does that matter? Lots of code can be rewritten in a different way. Indeed, that applies to most code.
If that's what you want to know, then ask that.
I don't see how that's relevant. We don't design asking ourselves how much a particular person remembered feedback on StackOverflow. We design based on what we think will provide the most value to the ecosystem as a whole. This will always be subjective, and it's entirely true that for every single release there will be people that disagree with the decisions made. This - applies to us and literally ever mainstream language ever created. I'm not sure what you're hoping to gain here. We thought investing in patterns was worthwhile. Nothing has changed our opinions here. Similarly, investing in covariant returns for interface implementation has not been worthwhile. These are our choices for the past, and relitigating them won't change them. Am you can do is try to work with us on future decisions. You're interested in certain things. The best of option for you is to make the best cases for investment there, and see if the community and designers agree with you. |
Inheritdoc is a thing.
Here's the thing. You consider that not acceptable. But we may disagree. Ultimately, we have to choose which tiny handful of features we pick. And if we think the workarounds are not so bad, then c'est la vie. Language design and scenario prioritization age ultimately entirely subjective processes. Your subjective assessment differs from ours. That's life. -- Reminder, my subjective opinion differs from many on the team. I likely have more rejected proposals than nearly anyone else out there. That's not something that bothers me. It just means figuring out better how to convince people and make good specifications for the ecosystem as a whole. |
Then find a way for this to be viewed as not important than all the other things that we and the ecosystem want "fixed finally" :-) I'm ok with the status quo. If you're not, then I wish you best of luck on what to do about that. |
@mikernet @HaloFour
I think inheritdoc won't work with a |
You can just place it wherever you want, including on new functions. |
You probably wanted to say "more important". I already listed some of the issues created for this problem before. |
Phone autocorrect strikes again |
Great. We'll consider this when evaluating our backlog. |
How often does that evaluation happen? I struggled to get any clear info on it re a different issue. |
It's fairly continuous. Occasionally we take a little break to do nothing but reevaluation. |
I highly doubt that is how this would work. If you look at my code, you'll see that the class states that it implements both interfaces, so it can specify how it implements the base interface member: class Evil : ISub, **IBase** It's kind of similar to how you can do: public class MyList<T> : List<T>, ICollection
{
public int Count => -999;
// or: int ICollection.Count => -999;
} I doubt that this feature would be designed such that you would be blocked from redeclaring an interface implementation. |
inheritdoc has a |
Inheritdoc doesn't even need to match signatures exactly. For example, it can point to a method with more parameters and it'll still match the common ones. Some fun examples: |
The text was updated successfully, but these errors were encountered: