题 如何简化设置对象的多个属性的C#代码?


我的代码看起来像这样:

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

加上我设置值的更多行 Question 里面的类 itemView

我认为答案是“不可能”,但只是把它作为一个问题,以防任何人知道一种方式。

我想要做的是找到一种方法来简化这段代码而不重复 itemView.Question 在每一行。


18
2017-07-18 07:16


起源




答案:


如果 Question 是一个 class (不是 struct),然后你可以将它分配给局部变量,并编辑:

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

你甚至不需要分配 q 回到 itemView.Question

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

编辑

请注意,如果情况可能有点模糊 Question 属于 itemView而不是一个领域。根据它的实现方式,您可能需要分配 q 回到 Question。在这种情况下,这个代码仍然是首选,以避免调用 Question 属性的getter方法反复出现。


12
2017-07-18 07:23



类/结构的区别在这里很重要,+1用于解释它和引用类型。这使得这个答案比其他类似答案更好。 - Cody Gray♦
因为这只是减少输入所以使用var q = itemView.Question这节省了5个字符 - pm100


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

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

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

19
2017-07-18 07:19



+1;即使他还没有做到这一点,无论如何这很有可能会奏效。 - Merlyn Morgan-Graham
为什么 (),如果你使用泛型构造函数? - VMAtm
@VMAtm:因为这是C#,而不是C ++? - Cody Gray♦
如果我们要创建新的实例,这只能完成 itemView.Question。如果只分配任何属性值,你会怎么做? (该对象已经有了它的实例) - ktutnik
@VMAtm:他们是 只要 在使用对象初始化程序语法时可选。否则,你 必须 在构造函数的调用中包括括号,默认与否。我无法想象一个很好的理由 不 在这里也可以使用它们。一致性对于可读代码很重要。 (有关) - Cody Gray♦


一种选择是您可以将属性转换为返回'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


9
2017-07-19 15:09





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

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

4
2017-07-18 07:20



当然,你可以。但这并没有真正简化代码或使其更容易阅读。 itemView 不是一个特别长的变量名称。 - Cody Gray♦
这就是为什么我说“缩短代码”而不是“简化”:-)。 - Hans Kesting
@Cody:重复访问 Question 虽然不是一个好主意。它可以是一个属性,并以OP显示的方式重复调用其getter方法。这绝对不是他想要做的。汉斯的例子几乎总是应该做的事情。 - Merlyn Morgan-Graham
@Merlyn:我不同意。你可以得到的任何C#/。NET编码风格指南都会告诉你所有的属性都应该被编写,这样它们几乎和使用字段一样便宜。 .NET团队的意图与普通程序员几乎无关;这非常重要,属性和字段在语法上看起来非常相似。 JITer将内联任何微不足道的内容 get 方法,使性能差异无法衡量。我当然不会这样做 所有 我的代码当然是理所当然的。 - Cody Gray♦
@Cody:我承认你的代码写得很好。非平凡的getter应该使用方法语法。但OP并没有重复 itemView但是 itemView.Question。 itemView.Question 需要一个(微小的)间接层来思考,以及子属性 Question 需要一个级别。重复它会放大间接性,并使其可读性降低。如果有人要更换,我完全同意你的意见 itemView.Prop1 = ...; itemView.Prop2 = ...; 同 var i = itemView; i.Prop1 = ...; i.Prop2 = ... - Merlyn Morgan-Graham


取决于您对控制的控制程度 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);

4
2017-07-18 07:28



我更喜欢这个想法:-) - MIMI
+1;这是一个好主意。见 得墨忒耳定律。我还要加一个 string username 这个函数的参数,而不是试图抓住 User.Identity.Name, 为了同样的原因。 - Merlyn Morgan-Graham