Although one could hook event from multiple control to the same method using the designer (as in Solution 4), I generally prefer to generate one method per control (and per event). This can make maintenance easier if you have to do something different for some controls.
Hooking event by code as in Solution 3 could make sense if you have a lot of controls in a single form that need that specific logic. Even then I would probably only hook controls directly on the form or in a specific panel.
However in practice, a form might contains some TextBox that does not contains numbers so using a loop migth not always be the best solution. Sometime, creating an array of controls (TextBox in this case) explicitly, might be the best solution.
Solution 2 make sense if it is something you want to do for any forms. In that case, you might want to have a property to enable/disable the special behavior. For example, if 0 is not valid in one case, then it does not make much sense to replace empty field by 0. One advantage of that solution is that you can add other features like special handling of decimal point from the numeric pad of the keyboard if regional setting use a comma instead of a dot for that separator or you get reformat number with thousand separator too.
Generally I tend to prefer the approach of having distinct handler calling a common function. It make it also easy to pass some additional information to the method like the "index" of the control or that data variable content or reference (and thus avoid ugly switch and cast in the common code).
For completeness, official documentation (MSDN) as proposed by solution 1 is always a good place to start.
private void textBox0_Leave(object sender, EventArgs e)
{
HandleTextBoxLeave(textBox0, 0);
}
private void textBox1_Leave(object sender, EventArgs e)
{
HandleTextBoxLeave(textBox1, 1);
}
private void textBox2_Leave(object sender, EventArgs e)
{
HandleTextBoxLeave(textBox2, 2);
}
void HandleTextBoxLeave(TextBox textBox, int index)
{
if (string.IsNullOrEmpty(textBox.Text))
{
textBox.Text = "0";
}
}