【问题标题】:Regarding Passing Many Parameters关于传递许多参数
【发布时间】:2008-12-02 04:30:41
【问题描述】:

我有大约 8-9 个参数来传递一个返回数组的函数。我想知道直接在函数中传递这些参数还是传递数组更好?哪种方法更好?为什么?

【问题讨论】:

    标签: c# .net asp.net .net-2.0


    【解决方案1】:

    如果我愿意做任何事情,那就是创建一个包含所有参数的结构,以获得良好的智能和强大的名称。

    public struct user 
    { 
        public string FirstName; 
        public string LastName; 
        public string zilionotherproperties; 
        public bool SearchByLastNameOnly; 
    } 
    public user[] GetUserData(user usr) 
    { 
        //search for users using passed data and return an array of users. 
    } 
    

    【讨论】:

    • WIN32 编程处于最佳状态! ;-)
    • 我是一名 VB 程序员,所以如果我的示例违反了一些 C# 设计规则,我深表歉意。但是,如果所有参数都链接到像“用户”情况下的自然对象,我更喜欢发送对象而不是参数。 ;)
    • 我不同意,您的示例看起来不错,因为您假设输入参数是相关的(用户的所有成员),但情况并非总是如此。
    • 我会这样做,但不使用结构。我会使用一个类,并且可能使其不可变。可变结构很容易以难以发现的方式被滥用。
    • 如果你向一个函数传递了超过 6 个参数,你可能会丢失一个。
    【解决方案2】:

    单独传递它们,因为:

    • 这是类型安全的方式。
    • IntelliSense 会在 Visual Studio 中提取它,当您编写调用函数时,您就会知道是什么。
    • 以这种方式执行会更快。

    如果参数确实是数组,那么传递数组。示例:

    对于看起来像这样的函数,请使用以下符号:

    Array FireEmployee(string first, string middle, string last, int id) {...}
    

    对于看起来像这样的函数,使用数组:

    Array FireEmployees(Employee[] unionWorkers) {...}
    

    【讨论】:

      【解决方案3】:

      Martin Fowler 的重构书中的 Introduce Parameter Object 重构涵盖了您的场景。这本书非常值得拥有,但对于那些不拥有的人,重构被描述为here。在publisher's site 和 Google 图书上也有预览。它建议不要用数组替换参数,而是用一个新对象。

      【讨论】:

      • 这里有更多关于模式等的很棒的资源:@​​987654323@。关于模式本身,我认为它的关键思想是将related参数分组为对象,而不是所有参数,而只是密切相关。
      • 不幸的是,@Dmitry,您发布的链接指向的网站看起来像是对 Martin Fowler 重构书的公然侵犯版权,因此您应该删除它。另一方面,您在应用此重构时澄清参数应该相互关联是有帮助的,谢谢。
      • 绝对不是。然后每个人都应该删除所有指向维基百科等的链接。 Sourcemaking 是模式目录、UML 图表、反模式等等。它只是整合了所有关于建筑的公共知识。您是否知道对这些事物进行更完整描述的更好资源?顺便说一下,它是在知识共享下获得许可的。我非常喜欢 Fowler,我认为他很棒,但他的 Refactoring 书只包含了部分知识。
      【解决方案4】:

      关于 Skeets 对上面我的示例的评论,他将使用类而不是结构,并且可能更清楚地在哪里使用类以及在哪里使用结构,我也发布了这个。我认为还有其他人对此也感到好奇。

      如我所见,使用类的主要原因是你可以让它不可变,但结构也可以吗?

      例如:

      struct user 
      { 
      public user(string Username, string LastName) 
      { 
          _username = Username; 
      } 
      private string _username; 
      public string UserName { 
          get { return _username; } 
      } 
      

      }

      当我们可以拥有属性、初始化器、字段以及类在结构中的所有内容时,我很长时间以来都觉得我不再知道类和结构之间的区别了。我知道类是引用类型,结构是值类型,但是在将其用作函数中的参数时,在上述情况下有什么区别?

      我在http://www.startvbdotnet.com/oop/structure.aspx 网站上找到了这个关于差异的描述,这个描述正是我在脑海中映射它的方式:

      结构可以定义为工具 用于处理一组逻辑 相关数据项。他们是 用户定义并提供一种方法 将不同的数据打包在一起 类型。结构非常相似 上课。像类一样,它们也可以 包含成员,例如字段和 方法。之间的主要区别 类和结构是,类是 引用类型和结构是 值类型。实际上, 结构用于较小的 轻量级物体不 持续很长时间并使用类 对于预期的较大对象 长期存在于内存中。

      也许这应该是一个自己的问题,但当我们对结构与类事物作为参数有不同的看法时,我觉得这是相关的。

      【讨论】:

      • 不要忘记,在最新版本的 C# 中,您可以通过使用只读自动属性来节省一些输入,如下所示: public string UserName { get;私人套装; }
      【解决方案5】:

      我假设您使用的是 C# 4,并且只能使用命名参数:

      FireEmployee(
          first: "Frank",
          middle: "",
          last: "Krueger",
          id: 338);
      

      这些使代码几乎与 VB 或 Smalltalk 一样具有可读性。 :-)

      如果不是,我会按照 Dave Markle 的说法。

      【讨论】:

        【解决方案6】:

        如果这是会被大量使用的库代码,并且如果某些参数具有可作为默认值候选的典型值,那么您应该考虑 Dave Markle 的建议,并提供一系列参数逐渐减少的重载.这是 Microsoft 框架设计指南中推荐的方法。

        或者,您可以使用 Stefan 的方法获得类似的效果,方法是使用成员初始化器设置默认值并使用一系列 ctor 重载。

        【讨论】:

          【解决方案7】:

          如果您真的不想单独传递参数,我建议创建一个封装所有参数的新类。为此,您可以(在 Java 中,很可能在 C# 中)在包含 gnarly 方法的类中声明一个公共内部类。这避免了浮动的类实际上只是辅助类型。

          【讨论】:

            【解决方案8】:

            我会说也单独通过它们。我不喜欢创建一个类,然后将该类作为参数传递的想法。它是一种标记耦合形式,这意味着由于一个类使用另一个类,因此进行更改将更加困难。重用一个类意味着您也必须重用另一个类。

            您可以使用接口来减少标记耦合,但这对我的口味来说开销太大,所以这就是我喜欢单独传递参数的原因。

            【讨论】:

              【解决方案9】:

              一个函数真的需要 8-9 个参数吗?在我看来,如果您需要这么多参数,那么您可能在该函数中做了太多不同的事情。尝试将代码重构为单独的函数,以便每个函数都有一个目的。

              【讨论】:

              • 然后呢?添加一个注释,应该始终按顺序调用所有 6 个相关函数?
              【解决方案10】:

              除非函数作用于数组,否则不要将它们作为数组传递,出于以下原因,我也不会创建新的数据结构来对参数进行分组

              1. 传递一个新的数据结构隐藏了函数真正需要的输入(它需要所有数据结构/部分吗?)

              2. 与 1 相关,它使 UT 变得更加困难(编写 UT 时需要重新创建整个数据结构)

              3. 如果输入参数不相关,您最终会得到一个新的数据结构,它将不相关的数据类型分组,只是为了让函数调用看起来更整洁

              4. 如果您选择将新数据结构传递给您的函数,则该函数不能在定义了新数据结构的范围内使用

              真正将每个参数传递给函数的唯一缺点是您可能无法将函数放入一行代码中,但不要忘记在函数调用之前需要填写的行你的数据结构。

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 2010-11-24
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2022-01-23
                相关资源
                最近更新 更多