具有相同参数类型的构造函数

7

我有一个Person对象,它有两个构造函数 - 一个接受int(personId),另一个接受string(logonName)。 我想要另一个构造函数,它接受一个string(badgeNumber)。 我知道这是不可能的,但似乎这可能是一个常见的情况。 有没有一种优雅的方式来处理这个问题? 我想这也适用于任何重载的方法。 代码:

public class Person
{
    public Person() {}

    public Person(int personId)
    {
        this.Load(personId);
    }

    public Person(string logonName)
    {
        this.Load(logonName);
    }

    public Person(string badgeNumber)
    {
        //load logic here...
    }

...etc.

13个回答

18

也许您可以使用工厂方法代替?

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() {}

7

您可以考虑使用自定义类型。

例如,创建LogonName和BadgeNumber类。

然后您的函数声明将如下所示...

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

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

这样的解决方案可能为您提供一个很好的地方来保存管理这些字符串格式和使用的业务逻辑。

2
我能想到四种选项,其中三种已经被其他人提到了:
  1. 按照工厂模式的方式进行操作,这是其他人建议的方法之一。这种方法的一个缺点是你不能通过重载实现一致的命名(否则你会遇到同样的问题),因此它表面上看起来不够干净。另一个更大的缺点是它排除了直接在堆栈上分配的可能性。如果你采用这种方法,所有东西都将在堆上分配。

  2. 自定义对象包装器。这是一个很好的方法,如果你从头开始编写代码,我会推荐这种方法。如果你有很多使用像徽章一样的字符串的代码,那么重新编写代码可能会使这个选项变得不可行。

  3. 在方法中添加一个枚举,指定如何处理字符串。这个方法可以工作,但需要重写所有现有的调用以包括新的枚举(尽管你可以提供一个默认值来避免一些麻烦)。

  4. 添加一个未使用的虚参来区分两个重载。例如,在方法上加一个 bool。标准库在一些地方采用了这种方法,例如 std::nothrowoperator new 的一个虚参。这种方法的缺点是它不太美观,而且不具有可扩展性。

如果你已经有了大量现有代码,我建议添加枚举(可能带有默认值)或添加虚参。虽然两者都不美观,但都相当简单易操作。

如果你从头开始编写代码,或者只有少量代码,我建议使用自定义对象包装器。

如果你的代码大量使用原始的 badge/logonName 字符串,但并没有大量使用 Person 类,则工厂方法是一种选择。


1
你可以使用静态工厂方法:
public static Person fromLogon(String logon) { return new Person(logon, null); }
public static Person fromBadge(String badge) { return new Person(null, badge); }

1

如果您正在使用C# 3.0,您可以使用对象初始化器

public Person()
{
}

public string Logon { get; set; }
public string Badge { get; set; }

您可以这样调用构造函数:
var p1 = new Person { Logon = "Steve" };
var p2 = new Person { Badge = "123" };

这是一个单行语句,但它缺少构造函数的优点 - 构造函数要求您提供一些参数,而初始化程序只是公共变量。 - drizin

1

不。

你可以考虑使用一个标志字段(为了可读性使用枚举),然后让构造函数使用它来确定你的意图。


1

那样做不行。建议您创建一个名为 BadgeNumber 的类,用于包装字符串以避免此歧义。


1

你不能有两个不同的构造函数/方法具有相同的签名,否则编译器如何确定要运行哪个方法。

正如Zack所说,我建议创建一个“选项”类,您可以在其中传递包含在自定义类型中的参数。这意味着您几乎可以传递任意数量的参数,并且可以随意使用选项,只需小心不要创建试图执行所有操作的单片式方法即可。

要么这样,要么投票支持工厂模式..


1

正如建议的那样,在这种情况下自定义类型是正确的方法。


0
根据您的业务限制:
public class Person
{
    public string Logon { get; set; } = "";
    public string Badge { get; set; } = "";
    
    public Person(string logon="", string badge="") {}
}
// Use as follow 
Person p1 = new Person(logon:"MylogonName");
Person p2 = new Person(badge:"MyBadge");

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接