[Proposal] Static extension methods #2505
Replies: 121 comments 83 replies
-
Leaving, for the moment, how would that be declared, can you show some examples of how would that be used and its benefit and how would the compiler translate it? |
Beta Was this translation helpful? Give feedback.
-
One possible syntax would be to copy F# type extensions: to extend a type, declare another type with the same full name (i.e. in the same namespace). |
Beta Was this translation helpful? Give feedback.
-
Example translation: using System.Threading.Tasks;
/*...*/ Task.FromException(ex) /*...*/ translates to /*...*/ SomeThirdPartyNamespace.TaskPolyfill.FromException(ex) /*...*/ |
Beta Was this translation helpful? Give feedback.
-
@SolalPirelli I considered this -- could also be an extension of The problem is -- what happens with instance methods? If we allow them, it would introduce a totally different syntax for instance extension methods. If we block them, it becomes a bit weird/inconsistent. |
Beta Was this translation helpful? Give feedback.
-
Where does this |
Beta Was this translation helpful? Give feedback.
-
@ashmind, as of now, the |
Beta Was this translation helpful? Give feedback.
-
A public static class in
I know -- this could be extended though. But at the moment I'm not advocating for that -- just looking at syntax options. |
Beta Was this translation helpful? Give feedback.
-
I really like the idea, and hope to get this feature! The syntax is a tricky part, I personally don't like using an attribute to recognize static extension methods, what about this? Essentially we add I'm open to other syntax suggestion. |
Beta Was this translation helpful? Give feedback.
-
Would something like this be possible? Since the class that declares such a method will probably need to be static anyway, it's a safe bet that it won't be able to implement an interface, so no possible conflicts there. However, just in case this restriction may be lifted somewhere in the future or a better way to differentiate from an explicit interface method implementation is needed, it might be better to throw in an additional keyword into the mix: |
Beta Was this translation helpful? Give feedback.
-
I don't know if this is possible at the CLR level, but would it be enough if the compiler would not treat as ambiguous if the same fully qualified name of exists in more than one assembly? I'm failing to see the benefit of:
Over:
Specially now that we have static imports. |
Beta Was this translation helpful? Give feedback.
-
I think the main benefit is discoverability. It just "feels" better. I really likes this proposal. As for syntax, I don't like the "this static Console" at all, this seems to make no sense at all other than it looking similar to existing extension methods: I agree with @HellBrick : public static class MyConsoleExtensions {
public static void Console.WriteColoredLine(string line, ConsoleColor color) {}
} This feels the cleanest IMO, and the Type.Method syntax already has a precedence for explicit interface implementations (IInterface.Method) so it doesn't look all that out of place. Of course static extension methods, just like regular ones, need to be hosted inside a public static class. I guess the compiler really just has to rewrite Console.WriteColoredLine method calls to MyConsoleExtensions.WriteColoredLine. It's probably mainly a question of intellisense discovering these? |
Beta Was this translation helpful? Give feedback.
-
It is interesting to also consider the design in a wider context. There is #112 for extension properties (no syntax yet?) and there might be static extension properties in the future. I can't say I'm a fan of |
Beta Was this translation helpful? Give feedback.
-
👍 Alternative syntax:
or
|
Beta Was this translation helpful? Give feedback.
-
What do you propose for overload resolution? |
Beta Was this translation helpful? Give feedback.
-
@paulomorgado Same rules as for instance extension methods (I don't remember all the details, but in practice it seems to work pretty well). |
Beta Was this translation helpful? Give feedback.
-
I'm a big fan of this feature. There are already multiple examples in the chat, but just to add a few more... 📄 Console::FlushInputBuffer [Expand]
📄 Console::PressToContinue [Expand]
📄 Array::newFromRanges [Expand]
📄 BindingFlags::All [Expand]
I have many more... |
Beta Was this translation helpful? Give feedback.
-
Yeah this would be very helpful in many situations, even extending BCL Types. For instance making a TimeSpan parser for ISO8601 format |
Beta Was this translation helpful? Give feedback.
-
I've had countless discussions, but very few have been achieved. I suggest that all friends give up participating in the discussion later, because your discussion will not receive any attention at all. |
Beta Was this translation helpful? Give feedback.
This comment was marked as spam.
This comment was marked as spam.
-
My reccomendation would be for the compiler to allow referencing a static method of a type when there's multiple types with the same name in scope, and just do ordinary method resolution on the method (#1988). So for example, you would define your own type ` namespace MyRootNamespace
{
public static class Console
{
public static void WriteGreen(string str) => ...
}
} Then when you were in a file, you could use both the methods on
The advantage of this approach is it doesn't require adding a new top level concept to C#, but acts pretty much the same way static extension methods would - if you import the right namespace, you magically see more methods on the Console class. And all for the cost of loosening a restriction on method resolution. |
Beta Was this translation helpful? Give feedback.
-
4436 I admit is very cool and in my mind addresses exactly the same problem
static extension methods do ie - allows developers who know what they are
doing to make life easier for developers who don't.
4465 doesn't really give you anything that you can't just do with
different syntax - 1407, 99, 4747 can be done with a weaver today.
…On Fri, Aug 6, 2021 at 2:54 AM Fred Silberberg ***@***.***> wrote:
And I quite comfortable with the assertion that none of the other features
you are considering, or have in your list of priorites, that you think are
so important - have that trait.
This is simply not true. Just a few of the things that are top of mind
from the C# feature list
<https://github.com/dotnet/roslyn/blob/main/docs/Language%20Feature%20Status.md>
:
- #4436 <#4436> - nothing
even approaching possible today.
- #4465 <#4465> - solves a
number of customer pain points that have been reported over the years.
- #1407 <#1407> - extremely
useful for the BCL and other large-impact users to improve perf for large
swaths of customers.
- #4747 <#4747> -
significantly improves the debugger experience for dsl customers, most
notably razor users.
- #99 <#99> - technically
possible in IL, but not possible in C# today.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#2505 (reply in thread)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAYTIZ3WWB7LHS67XDJU46DT3K64JANCNFSM4YGDQJOA>
.
Triage notifications on the go with GitHub Mobile for iOS
<https://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675>
or Android
<https://play.google.com/store/apps/details?id=com.github.android&utm_campaign=notification-email>
.
|
Beta Was this translation helpful? Give feedback.
-
Yes static extension methods are things I would like to have in C# |
Beta Was this translation helpful? Give feedback.
-
How about this? public static class ConsoleExtensions
{
public static void WriteColoredLine(static Console, string line, ConsoleColor color) {}
} Basically drop the |
Beta Was this translation helpful? Give feedback.
-
my reccomendation, use discards (_), as we would declear the class type to be extended, and we would never use a instance.
one more, could we also use extend operators like this?
|
Beta Was this translation helpful? Give feedback.
-
Static extension methods is also useful for compatibility in multi-targeting projects. New frameworks introduce some new API as static methods (e.g. in |
Beta Was this translation helpful? Give feedback.
-
Looks like this one has been here for a while now. FWIW, here's how I would like to use it. Let's say I want to write a static method called How would I make it easily discoverable? I could call my class I don't see any way to do this now. |
Beta Was this translation helpful? Give feedback.
-
Can someone from the community just make PR for this, without lots of involvement from dotnet team? Or it would be rejected without question, if its not a "champion" and "milestone"? This feature is requested and wanted for already around 8 years, and still active and discussed. I would love to do PR myself, if it would be reviewed, because it is feature I'm personally waiting for 3-4 years |
Beta Was this translation helpful? Give feedback.
-
There were some good ideas earlier, but some didn't consider generics, and some directly placed the type in the parameters. I believe that, in any case, extension methods should allow non-extension style invocation. Anyway, here are my thoughts: struct S
{
public static int F1() => 42;
public static void F2(int arg) { }
}
interface I
{
abstract static int F1();
abstract static void F2(int arg);
}
class C : I
{
public static int F1() => 42;
public static void F2(int arg) { }
}
static class Ex
{
public static void F1F2<this T>() where T : S => S.F2(S.F1());
public static void F1F2<this T>() where T : I => T.F2(T.F1());
}
static void Main()
{
S.F1F2();
C.F1F2();
Ex.F1F2<S>();
Ex.F1F2<C>();
} I think this is the most compatible with existing syntax and supports generics. This requires supporting value types as generic constraints (currently, it only accepts the type itself as a type argument). For reference types, I think static extension methods should be allowed to be called through derived types, there's no harm in that, but it's okay if it's not allowed. ------------------ [EDIT] ------------------- static class Ex
{
public static void F1F2() for S => S.F2(S.F1());
public static void F1F2<T>() for T where T : I => T.F2(T.F1());
}
static void Main()
{
S.F1F2();
C.F1F2();
Ex.F1F2();
Ex.F1F2<C>();
} |
Beta Was this translation helpful? Give feedback.
-
Looks like it has been about a year since there has been any activity on this thread. I would love for this proposal to gain momentum again, as this would be a very useful feature to have. My 2 cents 😄 |
Beta Was this translation helpful? Give feedback.
-
Problem
In modern C#, it is possible to add extension methods that imitate instance methods, but not static methods.
There are quite a few use cases for this:
Console
,Assert
,Path
, etc.This can be worked around if library authors switch to statically imported instance properties instead of classes, but it is extremely unlikely to be the right design choice for BCL APIs.
At some point, TPL team was using
TaskEx
for future previews, since they couldn't extendTask
-- complicating migration from preview to the real thing. And if someone wants to implement newTask.FromException
in pre-4.6 .NET -- they are out of luck as well, unless they choose a different class name.Design
Given the syntax currently used by instance methods, extending this to static doesn't feel straightforward.
One simple idea could be just to extend
[ExtensionAttribute]
:But please feel free to propose better designs. And I assume C# team did have some potential design for this in mind then choosing the instance syntax?
Pros
Cons
Community
Beta Was this translation helpful? Give feedback.
All reactions