【问题标题】:Constructors with the same argument type具有相同参数类型的构造函数
【发布时间】:2010-09-07 01:40:04
【问题描述】:

我有一个带有两个构造函数的 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...
    }

...等等。

【问题讨论】:

    标签: c# .net oop


    【解决方案1】:

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

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

    【讨论】:

      【解决方案2】:

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

      例如,创建 LogonName 和 BadgeNumber 类。

      那么你的函数声明看起来像......

      public Person(LogonName ln)
      {
          this.Load(ln.ToString());
      }
      
      public Person(BadgeNumber bn)
      {
          //load logic here...
      }
      

      这样的解决方案可能会为您提供一个很好的位置来保留控制这些字符串的格式和使用的业务逻辑。

      【讨论】:

        【解决方案3】:

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

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

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

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

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

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

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

        如果您的代码大量使用原始 badge/logonName 字符串,但不大量使用 Person 类,则可以选择工厂方法。

        【讨论】:

          【解决方案4】:

          没有。

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

          【讨论】:

            【解决方案5】:

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

            【讨论】:

              【解决方案6】:

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

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

              要么,要么投票给factory pattern..

              【讨论】:

                【解决方案7】:

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

                public static Person fromLogon(String logon) { return new Person(logon, null); }
                public static Person fromBadge(String badge) { return new Person(null, badge); }
                

                【讨论】:

                  【解决方案8】:

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

                  【讨论】:

                    【解决方案9】:

                    如果你使用的是 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" };
                    

                    【讨论】:

                    • 这是一个单一的(一行)语句,但它错过了构造函数的优势——构造函数要求你提供一些参数,而初始化器只是公共变量。跨度>
                    【解决方案10】:

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

                    【讨论】:

                      【解决方案11】:

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

                      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;
                        }
                      
                        ...
                      }
                      

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

                      【讨论】:

                        【解决方案12】:

                        取决于您的业务限制:

                        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");
                        

                        【讨论】:

                          【解决方案13】:

                          怎么样...

                          public Person(int personId)
                          {
                              this.Load(personId);
                          }
                          
                          public Person(string logonName)
                          {
                              this.Load(logonName);
                          }
                          
                          public Person(Object badgeNumber)
                          {
                              //load logic here...
                          }
                          

                          【讨论】:

                            猜你喜欢
                            • 1970-01-01
                            • 1970-01-01
                            • 1970-01-01
                            • 1970-01-01
                            • 1970-01-01
                            • 1970-01-01
                            • 1970-01-01
                            • 1970-01-01
                            • 1970-01-01
                            相关资源
                            最近更新 更多