Constructors with the same argument type

You could perhaps use factory methods instead?

public static Person fromId(int id) {
    Person p = new Person();
    p.Load(id);
    return p;
}
public static Person fromLogonName(string logonName) {
    Person p = new Person();
    p.Load(logonName);
    return p;
}
public static Person fromBadgeNumber(string badgeNumber) {
    Person p = new Person();
    // load logic
    return p;
}
private Person() {}

You might consider using custom types.

For example, create LogonName and BadgeNumber classes.

Then your function declarations look like...

public Person(LogonName ln)
{
    this.Load(ln.ToString());
}

public Person(BadgeNumber bn)
{
    //load logic here...
}

Such a solution might give you a good place to keep the business logic that governs the format and usage of these strings.


You have four options that I can think of, three of which have already been named by others:

  1. Go the factory route, as suggested by several others here. One disadvantage to this is that you can't have consistent naming via overloading (or else you'd have the same problem), so it's superficially less clean. Another, larger, disadvantage is that it precludes the possibility of allocating directly on the stack. Everything will be allocated on the heap if you take this approach.

  2. Custom object wrappers. This is a good approach, and the one I would recommend if you are starting from scratch. If you have a lot of code using, e.g., badges as strings, then rewriting code may make this a non-viable option.

  3. Add an enumeration to the method, specifying how to treat the string. This works, but requires that you rewrite all the existing calls to include the new enumeration (though you can provide a default if desired to avoid some of this).

  4. Add a dummy parameter that is unused to distinguish between the two overloads. e.g. Tack a bool onto the method. This approach is taken by the standard library in a few places, e.g. std::nothrow is a dummy parameter for operator new. The disadvantages of this approach are that it's ugly and that it doesn't scale.

If you already have a large base of existing code, I'd recommend either adding the enumeration (possibly with a default value) or adding the dummy parameter. Neither is beautiful, but both are fairly simple to retrofit.

If you are starting from scratch, or only have a small amount of code, I'd recommend the custom object wrappers.

The factory methods would be an option if you have code which heavily uses the raw badge/logonName strings, but doesn't heavily use the Person class.

Tags:

C#

.Net

Oop