-
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
Language Feature: Extension Everything #11159
Comments
Why we still require to name the extension class while it can be self explanatory like: public extension int { }
// instead of
public extension class IntegerExtensions : int { } Using class-base to specify the target type can get weird in case of generic, static or array types: public extension class IntegerArrayExtensions : int[] { }
// for defining static extension methods ..
public extension class ConsoleExtensions : Console { }
// would this be allowed?
public extension class GenericExtensions<T> : T /* where T : ... */ { } Alternatively, public extension int[] { }
public extension Console { }
public extension<T> T /* where T : ... */ { }
public extension<T> List<List<T>> { }
This would reserve class-base for when we have virtual extension methods (#258) to add interface implementations to existing types (#8127). |
I apologize if I misunderstood the proposal, but I don't think the way it treats return this._flattenCount; So,
So, to keep a this._cache = @this; Again, quite confusing. |
@alrz I think the name can be useful. You can use it to explicitly call the extension method as a normal method (e.g. |
It was messed up. Static members are accessed by qualifying with the extended type. I've fixed up the OP.
The |
@gafter Ok, now it looks good to me. |
@svick Currently you can not use
If that's your concern you'd better use the existing extension syntax (that'd be the benefit for the old syntax to be not totally deprecated). But I don't expect to be able to use extension methods as if they are static methods when I explicitly defined them in an
I didn't suggest that they be in the scope out of nowhere, just like what we have with extension methods, the containing namespace must be imported using I think naming classes like |
This compiles fine for me: using static System.Linq.Enumerable;
class Program
{
static void Main()
{
new int[0].ToList();
}
} |
@svick Oh right. But this doesn't |
While I do agree that naming an extension class is useful, I think that (formally) deriving this class from the extended class makes little sense overall. public class ClassToExtend
{
public ClassToExtend (int arg) { ... }
}
public extension class ExtensionClass : ClassToExtend
{
// For when constructors are supported.
public ExtensionClass (int arg1, int arg2) { ... }
}
...
// Unlikely the desired syntax, but should make sense if
// ExtensionClass is a descendant of ClassToExtend.
ClassToExtend a = new ExtensionClass(1, 2);
// Likely the desired syntax.
ClassToExtend b = new ClassToExtend(1, 2);
// Totally not what we need.
ExtensionClass c = ... In short, extension class is not a descendant of the extended class, so it shouldn't look like one. public extension class ExtensionClass<T> for ClassToExtend<T> { ... } |
Can you give some examples, how is that useful? I also note that if your extension class is generic, which it very may well be, you can't use |
@alrz public extension class<T> for T[] { ... } (I'm not insisting on // Only a for-part is something new; and no new keywords, contextual or not.
public class ArrayExtension<T> for T[] { ... }
// Easier to get as a special case of the previous. Still no good looking.
public class for ExtendedClass { ... }
public class<T> for T[] { ... } Names would allow to using static SomeNamespace.ExtensionClass<System.String>; Admittedly these all are pretty esoteric. Still the syntax you proposed does seem appealing to me, I'm just afraid it would complicate parsing, and the word "extension" is too good a word to make it a keyword. Maybe something like public extending<T> T[] { ... } |
Interesting 👍 Which existing types in CoreFx or third parties could benefit from the feature? |
|
Isn't this supposed to be static extensions? Why is "add the ability to have data associated with an instance (extension instance properties)" important?
That's when Java and Visual Basic start to look good for having extends and implements keywords. But for C#, I think it's too late to go that way. Another punctuation? |
@paulomorgado My point was this seems like a lot of design work for very little benefit over current state if adding state to the instance is not on the table. Having extension methods on static classes are the only truly new use cases in this spec, but even that is less useful than it once was with C# 6.0's Agree the ship has sailed long ago on |
@MgSam |
@quinisext I use extension methods extensively too. The only difference this proposal makes for properties is that instead of having extension methods On the other hand, if there is a realistic way to associate instance data, then it becomes a big win. WPF has the whole concept of "attached properties", which are absolutely nasty to declare, yet this proposal still doesn't fill the huge niche that those attempted to address. The C# design team tried to tackle extension everything once before and rejected it because the design was incompatible with this use case. |
I consider "extension static members" including "extension operators" the most important benefits of this. |
@MgSam public class ExtensionClass for System.Windows.Controls.Button // Whatever would be the syntax.
{
// You would still need to deal with abandoned values, but there is probably no good way
// to solve this problem in general case.
private static Dictionary<MyClass, int> values;
public MyIntProperty
{
get { return value[this]; }
set
{
values[this] = value;
}
}
// Some neat tricks.
public double CanvasLeft
{
get { return Canvas.GetLeft(this); }
set { Canvas.SetLeft(this, value); }
}
public RoutedEventHandler ClickHandler
{
get { return Click; }
set { Click += value; }
}
// Extension constructor.
public ExtensionClass (out Button variable)
{
var result = new Button();
variable = result;
return result;
}
}
// Now also this coud work.
var button = (Button)null;
var Panel = new System.Windows.Controls.Canvas
{
Children =
{
new Button (ref button)
{
CanvasLeft = 20,
MyIntProperty = 42,
ClickHandler = (s, e) => { DoSomething(); }
}
}
};
button.Click += MyOtherHandler; You can't do these things with Set/GetSomething(). Extension constructors may work well with immutable data. And extension operators would allow you to connect mathematical types that was initially unaware of each other. |
If the concept of "extended" state is to be on the table I would like to see something come out of the CLR that would enable such functionality without incurring the penalties associated with Beyond that, extension static methods, properties and operators do seem like they'd be worth it. Extension constructors are weird but I can see their value. Maybe that could lead to asynchronous constructors #6788. |
@quinisext That's a memory leak. Correct implementation would need something like WeakReference Dictionary. I'd rather see language support for extension fields than implementing this (I would probably get it wrong). |
@zippec
That's exactly what I meant by
As I said, I don't see a good general solution, that can be used as an implementation for extension fields/auto-properties. But that was not the point of the example. The point was to show that extension classes are worth implementing even without that particular feature. |
Another idea for the syntax - just use the type that we are extending, possibly with additional constraints. public extension class List<T> {..}
public extension class List<T> where T: List<int> {..}
public extension class List<T> where T: class {..}
public extension class List<T> where T: int {..} |
What would the name be for the generated static class if the developer doesn't explicitly provide one? Whatever it is would have to be predictable in order for a recompilation to not break existing consumers, and it would have to be resilient to collisions in case you want to extend two different classes named |
@VSadov public extension class int[] { ... } // Formally works but unnatural for c#. Also, as HaloFour said, what is the "predictable" name for |
The challenge here is to have a syntax very similar to a class definition, but yet we want to sneak in a type reference to a potentially more constrained instantiation of a type - like List< int >. My suggestion may not even be better than what @gafter proposed. Just another idea how we can abuse preexisting syntax. Having no name is ok. Not everything in the source ends up with formal names. |
Why though? Edit: Having
And I actually like the naming of the classes better than just using the type, it feels more like what's really going on: I'm making a new class that the compiler will treat as part of the original. |
Another idea would be to add a modifier for classes that is basically the extension-everything counterpart to Something like |
Why would you want to do that? this sounds like a bad idea to me because you shouldn't care whether people extending your types, it's their choice, not yours as they don't change any behaviour, they add new on top of existing one and atm the experience is unpleasant, I mean in order to "extend" types today, depends on the situation, you have to copy/paste the code, use wrappers or static classes and then at the consumer side you have to relate to some other type as opposed to the original type that was "extended" so why would you add a feature that tries to make the experience better and address this problem only to reintroduce the exact same problem? It makes sense to seal a class or individual methods because people don't want others to modify the behaviour but it doesn't make sense to prevent others from extending it unless the person is a "control freak". 😄 |
Will we still be required to use the |
Almost certainly yes |
@gafter Why is that? |
What's the alternative, @AustinBryan? |
@paulomorgado #998 (make |
@paulomorgado Make it so we don't have to use Just because you use |
@willard720, I find it informative. Can you find a situation where qualifying with |
I'm not sure I understand the current status of this issue. Thanks! |
@Sergio0694 language feature design is now tracked in dotnet/csharplang, this is an obsolete issue. |
@orthoxerox whoops, my bad, I was sure I was already in the |
@MadsTorgersen @Sergio0694 can you please point where in https://github.com/dotnet/csharplang/milestones is this #11159 feature located. I cannot find it. |
OK I found it dotnet/csharplang#192 Please do this as soon as possible! |
we can no longer call our extension member if it became a official implement |
all the other projects for "extension everything" have been closed. Is it possible to revive the project? Thanks! |
Most issues have been moved to discussions until they have more of a concrete proposal. I think this is the relevant discussion for this topic: dotnet/csharplang#5498
There is currently a working group looking into roles and extensions together as a project, so it is alive and well: https://github.com/dotnet/csharplang/tree/main/meetings/working-groups/roles With an evolving proposal here: https://github.com/jcouv/csharplang/blob/roles-spec/proposals/roles.md |
There are existing proposals/requests #3357, #4945, #5165, #5624, #6136, but this is a slightly different take. One difference is that qualification with
this
would be required inside, at least for access to extension members.Extension Everything for C#
This proposal gives a way to define new kinds of extension members. Today it is possible to define methods that act as if they are instance methods of the extended type. This proposal expands that capability, supporting both static and instance members, and supporting (or at least discussing) all of the kinds of members you might want to declare.
Here is an example that summarizes the new proposed syntax forms:
Limitations:
_flattenCount
above) work the same as extension members, even though not accessible outside.Substantial LDM design work will be required
e.M
to the set of extensions that might be designated by the access.The text was updated successfully, but these errors were encountered: