7

我有一个带有两个构造函数的 Person 对象——一个接受一个 int (personId),另一个接受一个字符串 (logonName)。我想要另一个接受字符串(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。

4

13 回答 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() {}
于 2008-08-27T20:43:10.887 回答
7

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

例如,创建 LogonName 和 BadgeNumber 类。

然后你的函数声明看起来像......

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

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

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

于 2008-08-27T20:41:16.210 回答
2

你有四个我能想到的选项,其中三个已经被其他人命名:

  1. 按照这里其他几个人的建议,走工厂路线。这样做的一个缺点是你不能通过重载来获得一致的命名(否则你会遇到同样的问题),所以它表面上不太干净。另一个更大的缺点是它排除了直接在堆栈上分配的可能性。如果您采用这种方法,所有内容都将在堆上分配。

  2. 自定义对象包装器。这是一种很好的方法,如果您从头开始,我会推荐这种方法。如果您有很多代码使用,例如,徽章作为字符串,那么重写代码可能会使这成为一个不可行的选择。

  3. 向方法添加枚举,指定如何处理字符串。这可行,但需要您重写所有现有调用以包含新枚举(尽管如果需要,您可以提供默认值以避免其中一些)。

  4. 添加一个未使用的虚拟参数来区分两个重载。例如,bool在方法上添加一个。标准库在一些地方采用了这种方法,std::nothrow例如operator new. 这种方法的缺点是它很丑陋并且无法扩展。

如果您已经拥有大量现有代码,我建议您添加枚举(可能带有默认值)或添加虚拟参数。两者都不漂亮,但两者都相当容易改造。

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

badge如果您有大量使用原始/logonName字符串但不大量使用类的代码,则工厂方法将是一个选项Person

于 2008-08-27T21:08:31.323 回答
1

不。

您可能会考虑一个标志字段(为了便于阅读而枚举),然后让构造函数使用 htat 来确定您的意思。

于 2008-08-27T20:41:33.400 回答
1

那是行不通的。您可能会考虑创建一个名为 BadgeNumber 的类来包装一个字符串,以避免这种歧义。

于 2008-08-27T20:42:59.733 回答
1

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

正如Zack 所说,我会考虑创建一个“选项”类,您可以在其中实际传递自定义类型中包含的参数。这意味着您几乎可以传递任意数量的参数,并使用选项做您喜欢的事情,只是要小心不要创建一个试图做所有事情的单一方法。

要么,要么投票给工厂模式..

于 2008-08-27T20:43:33.770 回答
1

您可以使用静态工厂方法:

public static Person fromLogon(String logon) { return new Person(logon, null); }
public static Person fromBadge(String badge) { return new Person(null, badge); }
于 2008-08-27T20:44:30.947 回答
1

正如已经建议的那样,在这种情况下,自定义类型是要走的路。

于 2008-08-27T20:46:07.167 回答
1

如果您使用的是 C# 3.0,则可以使用Object Initializers

public Person()
{
}

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

你可以这样调用构造函数:

var p1 = new Person { Logon = "Steve" };
var p2 = new Person { Badge = "123" };
于 2008-08-28T12:57:31.760 回答
0

我唯一能想到的处理你想要做的事情就是必须有参数,一个描述参数类型(一个带有 LogonName、BadgeNumer 等的枚举),第二个是参数值。

于 2008-08-27T20:42:00.873 回答
0

您可以切换到工厂样式模式。

public class Person {

  private Person() {}

  public static PersonFromID(int personId)
  {
    Person p = new Person().
    person.Load(personID);

    return p;
    this.Load(personId);
  }

  public static PersonFromID(string name)
  {
    Person p = new Person().
    person.LoadFromName(name);

    return p;
  }

  ...
}

或者,按照建议,使用自定义类型。您也可以使用泛型来破解某些东西,但我不推荐它以提高可读性。

于 2008-08-27T20:44:42.740 回答
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");
于 2021-02-25T16:25:41.820 回答
-2

怎么样 ...

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

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

public Person(Object badgeNumber)
{
    //load logic here...
}
于 2008-08-27T20:46:34.870 回答