It's not a silly question: it is a fundamental question.
The second way you describe is exactly how we used to do it, before OOP.
Every time you needed a slightly different set of parameters, you needed a new function name.
It's ok, when you have just "int" and "float", but whet happens when your overloads get more complex:
Add(int x1, int y1, int x2, int y2)
Add(Point p1, Point p2)
Now you need some slightly complicated names.
What about:
public static void Email(string body)
public static void Email(string body,
params MailAttachment[] attachments)
public static void Email(string to, string body)
public static void Email(string to,
string body,
params MailAttachment[] attachments)
public static void Email(string to,
string body,
string subject)
public static void Email(string to,
string body,
string subject,
params MailAttachment[] attachments)
public static void Email(string to,
string body,
string subject,
string fromAddress)
public static void Email(string to,
string body,
string subject,
string fromAddress,
params MailAttachment[] attachments)
public static void Email(string to,
string body,
string subject,
string fromAddress,
string fromDisplay,
params MailAttachment[] attachments)
public static void Email(string to,
string body,
string subject,
string fromAddress,
string fromDisplay,
string credentialUser,
string credentialPassword,
params MailAttachment[] attachments)
(Which I just ripped out of my email utils file).
What do you start calling each one? And how do you remember which one you need?
Basically, they make the code more readable, and make the logical flow simpler.