8

非常常见的场景:我有一个包含多个实例变量的类和一个接受多个参数的构造函数。我可以以某种方式将一个绑定到另一个吗?将所有参数分配给实例变量非常冗长,并且是约定优于配置原则可能(并且应该)涵盖的情况之一。我的示例代码如下所示:

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# 自动发挥它的魔力?

4

3 回答 3

5

C# 语言中没有任何内容涵盖这一点,不。虽然工具可以为您生成代码,但它们不一定会保持最新,您最终仍会看到代码存在且可见。在某些情况下,您可能使用反射来执行此操作,例如:

public MyClass(object param1, object param2, object param3, object param4)
{
    Helpers.PopulateFromConstructor(this, param1, param2, param3, param4);
}

...您需要以与参数相同的顺序指定值,并保持名称与字段等相同。当字段为readonly.

就我个人而言,我只是接受它-如果需要,可以使用工具生成代码,否则就忍受它。

请注意,您可能希望在设置字段时进行验证,尤其是在 nullity 附近。所以你的构造函数体实际上可能会像这样结束:

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 中汲取了这个想法,因为我在日常编码中使用它。这也是我们在Noda Time中使用的方法。)

于 2012-08-28T12:35:39.920 回答
4

“......可能(并且应该)被约定优于配置的原则所涵盖......”

“约定优于配置”通常适用于 API 或框架,例如 MVC 或实体框架,而不适用于语言本身。API 通常是一种集中的、可重用的、最重要的是简化功能的抽象。在这种情况下,口授约定有助于在不影响功能的情况下推动结构。

但是,编程语言并非如此。相比之下,该语言是广泛的、低级的和复杂的。它应该在不削弱语言价值的情况下尽可能少地限制其用户。假设这样一个广泛的“公约”将是非常规范的。除此之外,编译器假设具有给定名称的参数必须始终分配给具有相似名称的私有字段是很危险的。

一方面,您的约定并不是唯一常用的。例如,一种常见的编码风格建议使用下划线引导的私有字段 ( _param1),您的约定可能会错过。除了这些赋值之外,构造函数可能还有其他逻辑,在这种情况下,您的约定太简单了:“约定驱动”的代码应该在任何其他构造函数逻辑之前还是之后执行?

最重要的是,如何覆盖这样的约定?如果在构造函数中,你要param1以其他方式消费,你仍然执行约定吗?如果在构造函数中为 分配不同的值this.param1怎么办?您的约定应该发生在用户添加的代码之前还是之后?

即使是这些简短的问题——许多人将有非常不同但同样有效的答案——也足以表明这样的约定并不像看起来那样明显,也不容易定义。

于 2012-08-28T12:39:30.157 回答
2

虽然有很多插件可以做这种事情 - 值得注意的是,如果您 VS2010+ 的本机功能可以在不存在匹配的构造函数时从模型调用生成构造函数,您可以使用简单的键盘快捷键为您完成工作.

即,如果我是一个存根类:

class MyClass{

}

然后在某处的方法中,我写了这样的东西:

object p1, p2, p3;
//...  (get values for p1-3)
var a = new MyClass(p1, p2, p3);

当这样的构造函数不存在时,会出现一个小帮助按钮。如果你点击它,或者按下ALT+SHIFT+F10(默认)你会得到一个菜单,其中一个选项是生成一个存根构造函数,然后它将更改MyClass代码如下:

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

}
于 2012-08-28T12:45:50.653 回答