[Proposal] Extend keyword to force base calls from overrides including PRE and POST options #1734
-
So i just spent 20 minutes confused by some weird logical bug only to find i forgot to call a base method in the derived class, this makes me wonder why theres no supported optional keywords to force such things when you want more robust code that can fall apart by accidently forgetting something so minor. So i suggest some keywords: Base method implementations:
These are expected to be implemented in the derived classes, much like abstracts, so the extended equivalent must exist in the derived class. Derived method implementations: PreExtend: PostExtend: Extend:
They are different to overrides in that they contractually demand the programmer to call base one way or another. Could not think of a better word than extend though, but the keyword can be something better if one can think of a better word. It should be noted that the PRE and POST at compile time could possible just add the base call at the start/end of the override method like regular override - but the keyword makes it easier for programmers not to have to remember what does and what optionally requires the base method call. |
Beta Was this translation helpful? Give feedback.
Replies: 7 comments
-
Interesting. I've ran into this before as well. Also, it should the keyword should be lowercase, like all the other keywords in C#. It would be weird if it was the only one. What keyword should be used when the overriding function overrides? Should it be What about these things: protected virtual void Init() { }
protected preExtend void Bar() { }
protected postExtend void Baz() { }
...
protected preExtend void Init()
{
// base.Init() is implicitly called before this function executes
// even though the original method was only virtual
}
protected postExtend void Bar()
{
// Error, extend type mismatch
}
protected postExtend void Baz()
{
base.Init();
// do stuff
// Maybe a warning for calling base.Init() in a method that will do that anyways?
} |
Beta Was this translation helpful? Give feedback.
-
Also, please give a better title that isn't just `proposal'. Something more descriptive would be nice. |
Beta Was this translation helpful? Give feedback.
-
So if you added If you have a title suggestion i can edit it to improve it. |
Beta Was this translation helpful? Give feedback.
-
There is: So, you can write the above as: protected abstract InitWork();
protected void Init()
{
BeforeInit();
InitWork();
AfterInit();
}
protected void PreInit(){} // called before InitWork is called
protected void PostInit(){} // called after InitWork is called |
Beta Was this translation helpful? Give feedback.
-
With this approach there is no need to "remember". Anything that is required to be done is hardcoded in and you can't possibly 'forget' to call it. Instead, you only supply the part of the code that you really need to provide. |
Beta Was this translation helpful? Give feedback.
-
If you want to code using the pattern you've mentioned, you can already accomplish this today with Roslyn. specifically define your own 'PreExtendAttribute' and 'PostExtendAttribute's. Then just write this: [PreExtend]
protected virtual void PreInit(){}
[Extend]
protected virtual void Init(){}
[PostExtend]
protected Extended void PostInit(){} Then write a Roslyn Analyzer that checks for whatever contract/pattern you want with these methods and any subclasses. |
Beta Was this translation helpful? Give feedback.
-
Cyrus has beaten me to it, but this use case is reasonably well solved by the template method pattern. By reasonably well I mean it works as intended and is relatively painless (as painful as any regular protect abstract method). |
Beta Was this translation helpful? Give feedback.
If you want to code using the pattern you've mentioned, you can already accomplish this today with Roslyn. specifically define your own 'PreExtendAttribute' and 'PostExtendAttribute's. Then just write this:
Then write a Roslyn Analyzer that checks for whatever cont…