7

2つのコンストラクターを持つPersonオブジェクトがあります。1つはint(personId)を取り、もう1つは文字列(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...
    }

...等。

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

私が考えることができる 4 つのオプションがあり、そのうちの 3 つは既に他の人によって名前が付けられています。

  1. ここで他の何人かが示唆しているように、工場ルートに行きます。これの欠点の 1 つは、オーバーロードによって一貫した命名を行うことができないことです (そうしないと、同じ問題が発生する可能性があります)。もう 1 つの大きな欠点は、スタックに直接割り当てることができないことです。このアプローチを取ると、すべてがヒープに割り当てられます。

  2. カスタム オブジェクト ラッパー。これは良いアプローチであり、ゼロから始める場合にお勧めします。たとえば、バッジを文字列として使用するコードが多数ある場合、コードを書き直すと、これは実行不可能なオプションになる可能性があります。

  3. メソッドに列挙を追加して、文字列の処理方法を指定します。これは機能しますが、既存のすべての呼び出しを書き直して新しい列挙を含める必要があります (ただし、これを回避したい場合はデフォルトを指定できます)。

  4. 2 つのオーバーロードを区別するために、使用されていないダミー パラメーターを追加します。例:boolメソッドに a を付けます。このアプローチは、いくつかの場所で標準ライブラリによって採用されています。たとえば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

同じ署名を持つ 2 つの異なるコンストラクター/メソッドを持つことはできません。

ザックが言ったように、カスタム型に含まれるパラメーターを実際に渡すことができる「オプション」クラスを作成することを検討します。これは、好きなだけ多くのパラメーターを渡すことができ、オプションで好きなことを行うことができることを意味します。すべてを実行しようとするモノリシックなメソッドを作成しないように注意してください..

それか、ファクトリーパターンに投票してください..

于 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

工場スタイルのパターンに切り替えることができます。

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

あなたがやりたいことを処理するために私が考えることができる唯一のことは、パラメータタイプ(LogonName、BadgeNumerなどの列挙型)を記述し、2つ目はパラメータ値です。

于 2008-08-27T20:42:00.873 に答える
-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 に答える