很常见的场景:我有一个包含多个实例变量的类和一个接受多个参数的构造函数。我能以某种方式将一个绑定到另一个吗?将所有参数分配给实例变量非常冗长,并且是配置约定原则可以(并且应该)涵盖的情况之一。我的示例代码如下所示:
public class myClass
{
private object param1;
private object param2;
private object param3;
private object param4;
public myClass(object param1, object param2, object param3, object param4)
{
this.param1 = param1;
this.param2 = param2;
this.param3 = param3;
this.param4 = param4;
}
}
是否有简单方式摆脱这种情况并让C#自动完成它的魔力?
答案 0 :(得分:5)
C#语言中没有任何内容可以涵盖这一点,没有。虽然工具可以为您生成代码,但它们可能不一定会保持最新状态,您仍然可以使代码存在且可见。您可以潜在在某些情况下使用反射来执行此操作,例如:
public MyClass(object param1, object param2, object param3, object param4)
{
Helpers.PopulateFromConstructor(this, param1, param2, param3, param4);
}
...您需要以与参数相同的顺序指定值,并保持名称与字段等相同。您可能还会发现字段为readonly
时出现问题
就我个人而言,我只是吮吸它 - 如果你愿意,可以使用工具来生成代码,但除此之外只需要使用它。
请注意,您可能希望在设置字段时进行验证,尤其是在无效范围内。所以你的构造函数体可能实际结束了这样:
public myClass(object param1, object param2, object param3, object param4)
{
this.param1 = Preconditions.CheckNotNull(param1);
this.param2 = param2;
this.param3 = Preconditions.CheckNotNull(param3);
this.param4 = param4;
}
(当然,对于一个合适的Preconditions
类。我在Java代码中无意中从Guava中剔除了这个想法,因为我在日常编码中使用它。这是我们在{ {3}}也是。)
答案 1 :(得分:4)
“......可能(并且应该)被配置约定原则覆盖......”
“约定优于配置”通常适用于API或框架,例如MVC或实体框架,而不适用于语言本身。 API通常是一个集中的,可重用的,并且首先是简化功能的抽象。在这种情况下,规定惯例有助于在不影响功能的情况下驱动结构。
然而,编程语言并非如此。相比之下,语言是广泛的,低级的,复杂的。它应该尽可能少地限制用户,而不会稀释语言的价值。假设这样一个广泛的“惯例”将是非常规范的。除此之外,编译器认为具有给定名称的参数必须始终分配给具有相似名称的私有字段是危险的。
首先,您的惯例不是唯一常用的惯例。例如,一种常见的编码样式表示下划线引导的私有字段(_param1
),您的约定会错过这些字段。构造函数可能具有超出这些赋值的进一步逻辑,在这种情况下,您的约定太简单了:“约定驱动”代码是应该在任何其他构造函数逻辑之前还是之后执行?
最重要的是,如何覆盖这样的惯例?如果在构造函数中,您以其他方式使用param1
,那么您仍然执行约定吗?如果在构造函数中我为this.param1
分配了不同的值,该怎么办?您的约定应该在用户添加的代码之前还是之后发生?
即使是这些简短的问题 - 许多人将会有非常不同且同样有效的答案 - 足以表明这样的惯例并不像看起来那么明显,也不容易定义。
答案 2 :(得分:2)
虽然有很多插件可以做这种事情 - 但值得注意的是,如果VS2010 +的本机能力在匹配构造函数不存在时从模型调用生成构造函数,则可以使用简单的键盘快捷键来执行为你工作。
即。如果我是一个存根类:
class MyClass{
}
然后在某个方法我写这样的东西:
object p1, p2, p3;
//... (get values for p1-3)
var a = new MyClass(p1, p2, p3);
当这样的构造函数不存在时,会出现一个小帮助按钮。如果单击它,或按ALT+SHIFT+F10
(默认情况下),您将获得一个菜单,其中一个选项是生成存根构造函数,然后将更改MyClass
代码,如下所示: / p>
class MyClass
{
private object p1;
private object p2;
private object p3;
public MyClass(object p1, object p2, object p3)
{
// TODO: Complete member initialization
this.p1 = p1;
this.p2 = p2;
this.p3 = p3;
}
}