-
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
Extension properties for classes #112
Comments
I heard someone a few months ago mention the concept of "extension everything" when I brought up properties. If I'm not mistaken, the two most requested items which cannot be extended are:
If static extension members were available, it would be possible for someone to (for example) provide an extension member |
Ooh, static extension members! I'd like that. It would allow me e.g. extend the |
Even extension fields (for a reference type) would be possible by implementing them as the following: If extension field private static readonly ConditionalWeakTable<T, StrongBox<FieldType>> _extensionField_f;
public static FieldType get_f(T obj)
{
StrongBox<FieldType> box;
if (!_extensionField_f.TryGetValue(obj, out box))
return default(FieldType);
return box.Value;
}
public static void set_f(T obj, FieldType value)
{
StrongBox<FieldType> box = _extensionField_f.GetOrCreateValue(obj);
box.Value = value;
} |
@ErikSchierboom that is an awesome example of a use case. |
For me too it would be a very useful feature... |
@sharwell just found this, but btw I've created #996 today specifically for static extension methods. @ErikSchierboom A bit of an offtopic, but a weird thought: third-party libraries such as xUnit could adjust their API, allowing something like this. I don't expect BCL to do anything like that though, so static extension methods is still a better choice. |
@ashmind is right, we should think about this in a wider context. I think the only way to do so is to not cling to the existing syntax for extension methods (but of course keep it functional for methods for legacy support). What about something like this: public class MyClass { // we want to extend this
public int One { get; } = 1;
}
// new keyword extension for class
// for all intents and purposes this is a static class
public extension class MyClassExtensions : MyClass { // we don't inherit, for extension classes this means what we extend
// instance extension method
public int M() => return this.One; // no need to declare a this MyClass instance argument, compiler will automatically bind "this"
// instance extension property
public int P => this.M(); // via "this", one can access both extension and non extension members
// we can even do fields
private int someField; // this would get hoisted into some ConditionalWeakTable<MyClass, SomeGeneratedStructWithFeldValues>
// some "generatedstruct" would hold all fields for each "extension class"
public int P1 {
get { return someField; }
set { someField = value; }
}
// instance event
public event Action MyEvent; // underlying field against hoisted to ConditionalWeakTable
// static extension method
public static int SM() => return 42;
// static extension property
public static int SP => return 42;
private static int someField; // this would get hoisted into some ConditionalWeakTable<Type, SomeGeneratedStructWithFeldValues>
public static int SP1 {
get { return someField; }
set { someField = value; }
}
} Something like this would solve all these extension requests. |
@ashmind Interesting design, although I do hope static extension methods will get integrated. |
@chrisaut that's an interesting syntax. However, I think those 'extensions fields' may be pushing it too far: attaching state to another class in this way along with behavior just doesn't feel right or intuitive. Having said that, I kind of like the idea of marking class as an extension container for a specific target class and thus avoiding writing |
Sure, I agree it's kinda weird. But otherwise you can't do property setters or events. Well I guess properties could write store their value somewhere else. But events? I don't know of a good scenario for either of those, but why limit it? My main point was that it would feel natural to declare and use these when a dedicated extension class is introduced. |
It may appear natural to try that, but I'm afraid that's a feature that can easily be abused. If you want to attach an additional state to an instance of a class, I think in majority of cases it would be much better to either derive from it or to create a wrapper around it. Either way, you are explicit about your intentions. Using some automagical attached weak field references with an unclear lifetime as an alternative approach to design classes may have some appeal as a very cheap solution, but at the same time has a potential to lead to a bunch of the convoluted code that's gonna be difficult to maintain. I know this may sound paranoid, because in reality everything can be misused and abused. But what are the real use cases for the extension fields? Extension properties can make a lot of sense if their getters and setters just call some members of the extended class, but those are okay and don't need the backing extensions fields. The idea of extension events sounds weird; I encountered one case where they might have come in handy - providing a way to subscribe to an internal event of an internal type via reflection - but the point was once again to use the state of the extended object, not to add an additional state. And finally, if the language gets extension properties with explicit getters and setters and extension events with explicit add and remove methods, then the statefull extensions will be possible to implement manually in those (probably) rare cases when they actually make sense. |
The language design for extension properties may simple using indexes, just like: public static class MyClassExtensions
{
public static int Data[this MyClass obj]
{
get { return 0; }
set { return; }
}
}
var data = myObj.Data;
myObj.Data = 1; If there's more than one parameters in the indexer, this will raise and extension indexer property like public static class MyClassExtensions
{
public static int GetData[this MyClass obj, int index]
{
get { return 0; }
set { return; }
}
}
var data = myObj[0];
myObj[0] = 0; The extension properity is just a code-sugar for shorten writting. User may use a Dictionary other way to store the property value, or just provide a computed property. But anyway The background-field store and all the other things is not the bussiness for this feature itself. |
I'm not saying it's a good idea to attach state to an object. But, doing just that is a "natural" requirement/expectation if you want extension properties (and events).. Otherwise you cannot do auto-properties (compiler needs to emit a backing field), which may make the feature feel incomplete again. Even if that were disallowed, if you still allow property setters, developers will try to come up with their own solution and half of them will get it wrong in subtle ways. For instance they may create a Dictonary<MyClass, string> and store it there. Ooops, now the instance can never be garbage collected and you created a nice leak. Most developers don't even know about weak references or ConditionalWeakTable. So if we really want to discourage attaching additional state (essentially we don't want extension fields), then I feel the only way is to explicitly only allow Property Getters, and not support Setters or even getter only auto properties. Which may be fine. But my guess is people will bump into this limitation. I'm not sure if getters only would cover all of the scenarios people want. Or if we just say it covers enough of the scenarios and the rest is not worth it. Maybe I overlooked some, but I only saw one usage scenario mentioned in this thread. Should we try to collect more to better gauge what people actually want from this? |
I would like to see that one finally implemented in C#7, that's pretty a long time that I'm waiting for such a feature in the language. |
This seems like a trivial thing to add. My understanding is that the IL must already support this since properties are just syntax sugar for getter/setter methods. This means MS must have not added it for a stylistic reason, or because they foresee it being abused in all the ways outlined by previous participants. |
Wonderful, I think it will be really useful.
And I hope not only instance property can extension like current method extension. Static member also can extension. |
@kbirger Properties are mostly the accessor methods (there is a common naming convention but the runtime doesn't care) but they are also the additional metadata attached to the type that those accessor methods are a part of a property. There would be nothing stopping the compiler from recognizing and supporting that convention and making calls to I like the idea of extension properties and I think that they would make a lot of syntax cleaner feeling, but there are a couple of issues that concern me. For example, this mention of "state" or "extension fields". There'd really be no clean way to associate that data with the class instance itself, so the only way to really track that state would be through some kind of static dictionary. Such a pattern is a quick pit of failure into accidentally holding onto root references and preventing instances from getting collected ... ever. |
@HaloFour Wouldn't using something like |
@svick Of course, there are numerous ways to solve the technical problem, but the issue is that someone needs to be aware that it is a problem before they attempt to solve it. Making the concept of state (e.g. extension fields) an official part of the language where the compiler automatically implements best practices could solve for that. But even so the idea of "extension state" just feels ... icky ... to me. Granted, WPF already has the concept and an extension property syntax would work quite well with attached dependency properties I think. |
Adding state to a class will always come with a rather huge performance penalty. I am pretty sure they will not do this as it is very bad practice. Additionally, such properties would not take part in any kind of data binding and no PropertyChanged notifications would be raised. I do not see much benefit in extension properties. When you don't add state, you can get more or less the same behavior by just adding extension Get/Set methods. But static extension methods would be awesome. They would allow us to extend popular classes such as Math, Task, Assert, with more static methods, without the need for a new name ("..Ex"). |
Attached dependency properties already work with data binding. One example is
|
Well they only work with WPF's flavor of data-binding because that's how WPF was designed. IIRC no other form of data-binding in .NET recognizes that WPF-specific concept. |
@sgjsakura - |
I support indexer style. And it should allow naming indexer property I mean if code like this public static class MyClassExtensions
{
public static int GetData[this MyClass obj, int index]
{
get { return 0; }
set { return; }
}
} It should be used var data = myObj.GetData[0];
myObj.GetData[0] = 0; Also I wan to suggest to allow property indexer too with the same syntax |
@HellBrick , @chrisaut Attaching state to an object is perfectly valid and intuitive, as long as we understand what it means and how it should be used. The idea behind type extensibility is mainly to intervene into the inheritance chain and attach members (any members: fields, properties, indexers events etc.) that will be visible throughout the chain. The main class is not aware of the extensions and the extension is a an independent class of its own with a weak reference to an instance of the main class. It can only see the visible interface of the main class and interact with it. Understanding this is the basis for proper usage of type extension. Like any feature it can be misused but as I believe it has logical coherence it should not be prone to abuse. I hope I see this feature soon. I have plenty of uses for it, especially in controls. |
This is part of #11159. Closing as duplicate. |
Just scooping in some opinions.
For events, perhaps, but not necessarily for properties, granted setters might be more rare but they could occur natural to have a single setter that would change multiple properties underneath.
Why would that make it incomplete?... Does the limitations of extension methods compared to true instance methods make them feel incomplete?...
Considering that it's already perfectly possible to shoot your self in the foot like that with extension methods, I really don't see that extension properties will be the defining difference here. Those who will do that has already passed a stop sign in declaring a static reference to a collection with references to their objects, if they do that without thinking twice I think they will just go ahead and implement the "SetMagicProperty(this SomeClass key, object value) { map[key] = value; }" method... Which C# will happily let you do.
I really don't see any reason not to allow Setters when we considering that they are really just specially named methods under the hood with some meta data information. Adding state to a class, e.g. though extension fields feels extremely natural and is very useful (consider dynamic languages). But I can certainly imagine that is has some extreme implications on the CLR, so here I would let the team make the call to weather or not to support them, I would probably stay away from them for now. |
Yeah sharing code in XF is a real pain because this feature does not exist. All the code in WPF, Silverlight, and UWP uses "DataContext", but the same thing in Xamarin Forms is inexplicably "BindingContext". If I could put an extension property on all BindableObjects, immediately, code sharing would be a lot easier. |
@MelbourneDeveloper: Extension properties are not real properies. They cannot be seen by reflection on the target object, so they will not be picked up by any data binding based framework such as Xaml UWP or Xamarin Forms. This will not help you in any way. |
I'd like to point out that my favourite use case for this feature is/will-be extension properties on |
@Groostav patching a weakly-typed API like DataRow by adding strongly-typed extensions to it is, well, a bit sad... Dapper (or a full-fledged O/RM) does sound like a better option... |
This would be great because I do not want to derive from System.Reflection.Assembly to hope that my overridden Location property only works from an assembly loaded from a zip file. What I would like is something liek this:
which would be nice for those wanting to override the original behavior of the System.Reflection.Assembly.Location to return what they want without extensive hacking on it. However tgat would mean all frameworks having that class would need to add LocationExtension to that class and the class that does the actual code providing the current functionality to do like:
On it’s getter. And in this way, it only provides the extension override when and only when a file is loaded from the static LoadFromZip method. After some thought I think ot would be better to make it a paramiterless method and then use the invoke function I think. |
Extension methods were added for LINQ in C# 3.0, but I commonly run into cases where extension properties would be useful. Eric Luppert, who used to be on the C# team at Microsoft, wrote that extension properties were not implemented because other features were deemed more valuable. I think it is time to look at that decision again.
The text was updated successfully, but these errors were encountered: