Proposal: Customisable overload resolution #4869
Replies: 60 comments
-
Same (in principle) as #964? |
Beta Was this translation helpful? Give feedback.
-
This could lead to subtle bugs where the consumer of your API would get different overloads depending on which version of C# is in use. |
Beta Was this translation helpful? Give feedback.
-
@bondsbw Not if these only came into play where there would previously have been a compile error due to overload ambiguity. |
Beta Was this translation helpful? Give feedback.
-
I don't think that's the case, overload resolution is designed to be more predictable and less surprising, when it comes to backward compat, you're almost alway on your own. but I agree, OverloadResolution.cs is not long enough to be actually useful. |
Beta Was this translation helpful? Give feedback.
-
@jnm2 Good point, though the examples in the proposal already have valid resolutions. |
Beta Was this translation helpful? Give feedback.
-
I can see two scenarios for this issue: B) This should be prevented and only newer C# compilers allowed to compile such code.
Overload resolution has been "surprising" to me (and others I've tutored over the years) since the introduction of generics continuing to string interpolation. I think |
Beta Was this translation helpful? Give feedback.
-
There have already been cases where a major version of C# changed overload resolution in places that the resolution failed to do the thing API authors expected (aka "Betterness").
If this was true, then Betterness/Better Betterness would never have happened and Bestest Betterness wouldn't even be on the table. |
Beta Was this translation helpful? Give feedback.
-
@Joe4evr But doesn't "betterness" only affect code that didn't previously compile? |
Beta Was this translation helpful? Give feedback.
-
@Joe4evr The second sentence from your link to Bestest Betterness:
I think @Neme12 is right. |
Beta Was this translation helpful? Give feedback.
-
Also:
This would not only make breaking changes to overload resolution itself (not just removing some candidates), but also make it customizable? That seems like a disaster. Overload resolution is already complicated as it is. But at the very least you can expect it to be the same for everyone. |
Beta Was this translation helpful? Give feedback.
-
Is it really that hard to just make a new method name? |
Beta Was this translation helpful? Give feedback.
-
@Neme12 the OP discuss concerns with updating existing APIs, implying that the old (less ideal) method will still exist, and duly the new (less terrible) method will be competing for the name, so this is kind of rejected by assumption for the use-cases. |
Beta Was this translation helpful? Give feedback.
-
I don't think this feature is about backward compatibility, I don't want backward compatibility here, I want to explicitly change overload resolution priority when targeting a newer language version. I specifically want improved functionality by using a newer compiler. (IE: choosing the FormatedString overload opposed to the string one).
To give a more specific example: I'm developing a template based code generator based on C# 6.0 interpolated strings (If you want to see some details about it you can see here but for the purpose of the discussion I'll replicate the examples here). In the generator, FormatedString is used to enhance the features of the generator, some examples: Write($" This is a status message: {(Success, ConsoleColor.Green)}"); // this adds colorisation to output
Write("A different Message"); // /Can't have this overload ... as this is a string one, and the previous one won't work
// so instead need a new name
WriteS("A different message"); // This works, different method name, but now you can do this:
WriteS($" This is a new status message: {(Success, ConsoleColor.Green)}"); // which doesn't work because this is a string overload
//and now you have to juggle between overloads Same with logging, I would like to contextually choose to log structured and unstructured messages based on whether I use a string or a formatted string, not based on method names. |
Beta Was this translation helpful? Give feedback.
-
@VisualMelon What's wrong with making a new name for the "less terrible" method? And as I understand it, it's not that the old method is "terrible" anyway. You don't always need interpolation. When you do, you call a different method that has a "Formattable" or some other suffix. And when you use that name, at least you can be sure that this is going to do the right thing. Let's say if we take the example of SQL and auto-converting interpolation to SQL parameters. In this case, you really want to be explicit about this and not rely on overload resolution (especially when it differs between different language versions!) to prevent SQL injection. With a different method name, this will also be a lot less fragile - if you accidentally pass in a string, the code won't compile. |
Beta Was this translation helpful? Give feedback.
-
@popcatalin81 Why can't you make a new method called |
Beta Was this translation helpful? Give feedback.
-
@HaloFour We don't need a reason not to do things. What precise rule are you proposing that would forbid this set of method declarations?
@jnm2 What precise rule changes are you proposing that would make it "smarter"? Overload resolution is one of the most delicate areas of the language and we are reluctant to touch it without very good cause and proof that the change is sound. I'm not confident that we even have cause for a change here. |
Beta Was this translation helpful? Give feedback.
-
@gafter The rule would be that if all the overload candidates are |
Beta Was this translation helpful? Give feedback.
-
I don't disagree. I just think that it's a subpar experience to be able to have this combination of overloads marked with That said, I'm probably in agreement with @jnm2 that given the option of |
Beta Was this translation helpful? Give feedback.
-
Even if other parameter positions make some other method preferable for other reasons (e.g. parameter type of
We don't even have a "plan" to add support for |
Beta Was this translation helpful? Give feedback.
-
@gafter No, only if all other things are equal. The preference for
I'm answering your question to me with a question which it seems you'll inevitably have to deal with if the championed proposal #1757 is to go forward. |
Beta Was this translation helpful? Give feedback.
-
I don't agree that your question is one we'll have to deal with. |
Beta Was this translation helpful? Give feedback.
-
@gafter I'm sensing some kind of pushback to our questions. I apologize if I've said something out of place. |
Beta Was this translation helpful? Give feedback.
-
I think this is a question that almost every language feature has to deal with. That is, for any given language feature, you basically need to ask (IMO): "Can CoreFX use this?" (or replace
I think, for the most part, the language has been fairly good in this regards (see That being said, given that |
Beta Was this translation helpful? Give feedback.
-
I agree. But I also think that @jnm2 has a really good point. If the BCL were to start adding new The solution is somewhat easy. Support |
Beta Was this translation helpful? Give feedback.
-
@HaloFour, right. CoreFX has some additional considerations since they can/will be used from multiple compiler versions. In that case, they may need to keep both
|
Beta Was this translation helpful? Give feedback.
-
@jnm2 I'm not intending to push back against the asking of questions, I'm just not convinced in this case that an answer is needed. I'm very reluctant to modify overload resolution in general because it is one of the most delicate areas of the language. I believe that API authors can reasonably migrate as @tannergooding has suggested. This may require that program authors are capable of specifying which version of a platform API they are compiling against. If you want to use new versions of the platform APIs, you might have to upgrade both your platform version and your compiler. Of course we need to make sure that VB.Net, F#, and any other widely used languages have new versions that understand the new constructs. |
Beta Was this translation helpful? Give feedback.
-
I understand that overload resolution is painfully complicated already and I wouldn't suggest modifying any existing rules. I'd suggest that the "only" (almost as bas as "just") change would be that if two overloads are equally good and one has
I disagree. The BCL can't reasonably migrate due to downlevel compiler compatibility. The same would be true with any larger project with a wide developer base. Those projects would all either be left on |
Beta Was this translation helpful? Give feedback.
-
mscorlib cannot use that. String.Format cannot do that, Console.Writeline can’t do it. All of these would want to take advantage of params span |
Beta Was this translation helpful? Give feedback.
-
These are the types and methods from
Some of these methods would greatly benefit having a
|
Beta Was this translation helpful? Give feedback.
-
@popcatlin81 A |
Beta Was this translation helpful? Give feedback.
-
Customisable overload resolution
This is a proposal to add a customization mechanism for the C# language, to control method group overload resolution.
Summary:
C# overload resolution is designed for best possible backward compatibility in the general case. Some special types of libraries and evolving APIs meet some difficulties in implementation when their needs diverge from the C# language rules. IE: instead of being focused on compatibility they are focused on performance or improved functionality :
Motivation:
Design
[PreferredOverloadAttribute]
to designate higher priority method overloads from a valid method group.PriorityBoost
integer property to allow specifying different priorities for valid candidate methods.PriorityBoost
value, the regular overload resolution rules will apply.Formattable string example:
This is a case where a structured Logging library will indicate the preference to use the formattable string overload over the string overload in order to enhance its API usage.
C# 7.2:
unformatted
C# 7.2+:
formattable string
ISpanFormattable example:
This will allow libraries to take advantage of newer performance oriented features without introducing new method names that will require source changes, only recompilation with the latest compiler:
C# 7.2:
object
C# 7.2+:
ISpanFormattable
params Span<T> example
Champion "params Span<T>"
This will allow method overload resolution to chose the
Span<T>
based overload instead of theint[]
overload chossing the allocation free path,Beta Was this translation helpful? Give feedback.
All reactions