【问题标题】:How can I simplify C# code that sets multiple properties of an object?如何简化设置对象多个属性的 C# 代码?
【发布时间】:2011-07-18 07:16:32
【问题描述】:

我的代码如下所示:

itemView.Question.AnswersJSON = itemView.Answer.ToJSONString();
itemView.Question.Modified = DateTime.Now;
itemView.Question.ModifiedBy = User.Identity.Name

还有更多我为itemView 中的Question 类设置值的行。

我认为答案是“不可能”,但只是将其作为一个问题提出,以防万一有人知道。

我想做的是找到一种方法来简化此代码,而无需在每一行中重复 itemView.Question

【问题讨论】:

    标签: c# coding-style


    【解决方案1】:

    您是否将 itemView.Question 实例化为方法的一部分?

    如果是这样,你可以这样做:-

    itemView.Question = new ItemViewQuestion()
    {
      AnswersJSON = itemView.Answer.ToJSONString(),
      Modified = DateTime.Now,
      ModifiedBy = User.Identity.Name
    };
    

    【讨论】:

    • +1;即使他还没有这样做,也很有可能无论如何都会奏效。
    • 如果使用泛型构造函数,为什么要()
    • @VMAtm:因为这是 C#,而不是 C++?
    • 只有在我们即将创建itemView.Question 的新实例时才能这样做。如果只分配它的任何属性值,你会怎么做? (对象已经有它的实例)
    • @VMAtm:当您使用对象初始值设定项语法时,它们是可选的。否则,您必须在对构造函数的调用中包含括号,无论是否默认。而且我想不出一个很好的理由在这里也使用它们。一致性对于可读代码很重要。 (Related)
    【解决方案2】:

    一种选择是您可以将属性转换为返回“this”的方法。

    那么你可以写:

    itemView.Question
        .AnswersJSON(itemView.Answer.ToJSONString())
        .Modified(DateTime.Now)
        .ModifiedBy(User.Identity.Name);
    

    我听说过这种风格叫做“流利的界面”,觉得它很方便。我有时会创建属性和一个匹配的 set 方法返回 'this',称为 SetXXXX。

    用于单元测试的流行 Rhino Mocks 框架使用它。更多示例:http://www.codeproject.com/Articles/99542/Guidelines-to-Fluent-Interface-design-in-C-Part-1

    【讨论】:

      【解决方案3】:

      如果Questionclass(不是struct),那么您可以将其分配给一个局部变量,然后对其进行编辑:

      Question q = itemView.Question;
      q.AnswersJSON = itemView.Answer.ToJSONString();
      q.Modified = DateTime.Now;
      q.ModifiedBy = User.Identity.Name
      

      您甚至不必将q 分配回itemView.Question

      这是因为 C# 中的类是 reference types。如果您将引用类型的实例分配给局部变量,或将其传递给函数,则对该实例的更改将反映在您引用同一实例的任何地方。

      编辑

      请注意,如果QuestionitemView 的属性而不是字段,则情况可能会有些模糊。根据它的实现方式,您可能必须将q 分配回Question。在这种情况下,还是首选这段代码来避免重复调用Question 属性的getter 方法。

      【讨论】:

      • 类/结构的区别在这里很重要,+1 用于解释它和引用类型。这使得这个答案比其他类似的答案更好。
      • 因为这是关于减少打字然后使用 var q = itemView.Question 这可以节省 5 个字符
      【解决方案4】:

      根据您对Question 类的控制程度,分离设置元数据的职责可能是一个想法:

      class Question {
          ...
          public void SetAnswer(Answer answer) {
              this.AnswersJSON = answer.ToJSONString();
              this.Modified = DateTime.Now;
              this.Modified = User.Identity.Name; // or pass the user into SetAnswer()
          }
      }
      
      // in your UI code:
      itemView.Question.SetAnswer(itemView.Answer);
      

      【讨论】:

      • +1;这是一个好主意。请参阅Law of Demeter。出于同样的原因,我还会向该函数添加一个string username 参数,而不是尝试获取User.Identity.Name
      【解决方案5】:

      如果该问题是一个类,那么您可以稍微缩短代码:

          var q = itemView.Question;
          q.AnswersJSON = itemView.Answer.ToJSONString();
          q.Modified = DateTime.Now;
          q.ModifiedBy = User.Identity.Name
      

      【讨论】:

      • 当然可以。但这并没有真正简化代码或使其更易于阅读。 itemView 不是一个特别长的变量名。
      • 这就是为什么我说“缩短代码”而不是“简化”:-)。
      • @Cody:重复访问Question 不是一个好主意。它可能是一个属性,并且以 OP 显示的方式引用它将重复调用其 getter 方法。这绝对不是他想做的。汉斯的例子几乎总是应该做的。
      • @Merlyn:我不同意。任何您可以掌握的 C#/.NET 编码风格指南都会告诉您,所有属性都应该被编写,以便调用它们实际上与使用字段一样便宜。 .NET 团队希望这种区别几乎与普通程序员无关。这非常重要,以至于属性和字段在语法上看起来非常相似。 JITer 将内联任何琐碎的get 方法,这使得性能差异无法衡量。当然,我当然不会在我的所有代码中遵循这一点。
      • @Cody:我承认你的观点是写得很好。一个重要的 getter 应该使用方法语法。但是 OP 不是重复itemView,而是itemView.QuestionitemView.Question 需要考虑(微不足道的)间接级别,Question 的子属性需要更高级别。重复它会放大这种间接性,并使其可读性降低。如果有人将itemView.Prop1 = ...; itemView.Prop2 = ...; 替换为var i = itemView; i.Prop1 = ...; i.Prop2 = ...,我完全同意你的看法
      猜你喜欢
      • 1970-01-01
      • 2021-10-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-12-23
      • 2011-07-21
      • 1970-01-01
      相关资源
      最近更新 更多