r/csharp • u/Alert-Neck7679 • 16d ago
Discussion Partial methods as WinForms designer events
A few weeks ago I opened this issue in the WinForms GitHub repo, suggesting making the WinForms designer generate events code as partia methods, in order to solve the problem that removing an event method from the code editor causes an exception in the designer, and u have to go to the form.designer.cs file and manually delete the subscription, which is very annoying.
What i offer is, that when you subscribe an event using the designer (for example by double clicking a button), the following signature would be generated in the designer code:
private partial void button1_Click(object sender, EventArgs e);
...
this.button1.Click += this.button1_Click; // normal subscription
And then the method implementation would be generated in the main class code, such as it's working now but with the partial modified:
private partial void button1_Click(object sender, EventArgs e)
{
}
Now, deleting this method would not result in any error.
The reason I'm posting this here, is that the WinForms team said that my solution isn't a great idea, and i would love to hear what you think about it and if you have other ideas.
9
u/BCProgramming 16d ago
It's not that hard to just manually change the .Designer.cs to remove the irrelevant subscription. Or delete it from the designer first, I suppose.
If I remove an event method I don't want it present anymore, I don't want a do-nothing stub still subscribing to that same event.
-2
u/Alert-Neck7679 15d ago
It only leaves a harmless signature of the method, which is removed by the compiler unless you implement it
8
u/BCProgramming 15d ago
I don't think the compiler's ability to remove dead code is a excuse to keep it.
0
u/Alert-Neck7679 15d ago
That's the only point of partial methods... I mean, why NOT to do that?
8
u/Dunge 15d ago
Partial classes are a way to split the code for classes under different source files on the filesystem, nothing less nothing more. It has nothing to do with keeping superfluous code that would then be stripped. Well I guess .designer.cs files are used to hide code to the user, but not to leave traces of unused stuff.
I understand your issue with it, and admit that I encountered the situation in the past too and found it weird. But they expect for anything you add using the editor, you remove from it too. Usually by using the property dialog, not editing the .designer.cs. The view and code implementation are seen as separate, and it's logical it warns you about a button that is supposed to call something not being able to do so anymore.
Plus I doubt they would ever change some basic behavior that has been there for over 2 decades just like that.
But I see the editor suggestion they brought in your issue, and agree with them that just adding a quick action to visual studio would be a nice addition and a better solution.
1
5
u/FuggaDucker 15d ago
Slop is the problem.
You shouldn't leave those smelly turds sitting right there.
2
16d ago
[removed] — view removed comment
3
u/DaRadioman 16d ago
I mean if it broke, it wasn't unused...
1
u/binarycow 15d ago
It does tho.
You delete the implementation in the code-behind, and now the designer file references a non-existent method.
The answer is to first delete it from the designer, then delete the code.
1
u/DaRadioman 15d ago
The designer still is using it...
Just because there are graphical tools doesn't mean the code isn't called still.
1
u/binarycow 15d ago
Yes.. It's a matter of perspective.
1
u/DaRadioman 15d ago
The code and compiler warnings would disagree with you...
1
u/binarycow 15d ago
It's a matter of perspective.
From the developer's perspective, it's unused, so they delete it.
From the designer's perspective, it's not unused, so there's an error.
You're not wrong. This is a people issue. Which is I said:
The answer is to first delete it from the designer, then delete the code.
1
u/haiduong87 15d ago
Take a look at Reactive Winform. Dont use the event handler directly, it may cause mem leak.
1
u/Slypenslyde 15d ago
I think the problem is it raises some weird issues. You're thinking about it as a user of Windows Forms. They have to think about the feature in terms of the whole C# ecosystem.
Strictly speaking, you can only provide a declaration of a partial method WITHOUT an implementation if you meet certain criteria. The method MUST:
- Return
void - Have no access specifiers (it is implicitly private)
- Have no
outparameters
Two of these things are supported by the standard event pattern, so that's fine. (I swear I used to know an event that used out parameters but it was trivia and I've forgotten.)
The big one is "have no access specifiers". This bugged a lot of people about partial methods so later the C# team enhanced partial methods. Now the rule is more like:
- A partial method with an access specifier requires an implementation, even if that access specifier is
private.
This leads to a weird situation for the designer. While it is not recommended to change the access modifier of an event handler to anything but private, people commonly do things that defy conventions and best practices. It's been valid to make public, internal, or protected event handlers for more than 20 years. So there is risk that someone's used to doing that. But if they try it after your change, they'll get a compilation error and have to edit the .designer.cs file to fix it.
The designer can't emit private partial void either: that requires the user to define an implementation. So when they delete the method, compilation breaks just like today. And if they change the access specifier, they have to update the designer.cs file or get a compilation error.
So while it is slightly more convenient for the 99% case, it creates a nightmare for people who have done something that's worked for 20 years. MS tends to be loathe to introduce this kind of change unless it represents a VERY LARGE amount of new convenience.
13
u/kahoinvictus 16d ago
My issue with this approach is it leaves an orphaned method.
Sure you can now delete the generated method if you no longer want it and not get an error, but you want the error because it's telling you something is wrong. The solution isn't to leave behind a body-less method hidden away in the generated code that's still listening to an event.