【问题标题】:C# Bind constructor parameters to instance variablesC# 将构造函数参数绑定到实例变量
【发布时间】:2012-08-28 12:27:22
【问题描述】:

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

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

【问题讨论】:

  • CodeRush 或 JustCode 等插件可以自动为您生成该代码。
  • 你也可以看看使用代码 sn-ps:msdn.microsoft.com/en-us/library/ms165392(v=vs.80).aspx 但是,像 BigYellowCactus 提到的那些工具会给你带来更好的生产力。
  • 将 Resharper 添加到上面的列表中。
  • @Jan 你能准确地拼写出你提出的约定吗?
  • @Serg, "将构造函数参数映射到同名同类型的实例变量"

标签: c# constructor


【解决方案1】:

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

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

...您需要以与参数相同的顺序指定值,并保持名称与字段等相同。当字段为readonly时,您可能还会发现问题。

就我个人而言,我只是接受它——如果你愿意,可以使用工具来生成代码,否则就接受它。

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

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 中使用的方法也是。)

【讨论】:

    【解决方案2】:

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

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

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

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

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

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

    【讨论】:

    • 哇,很多优点。我想我正在寻找的是“让我的生活轻松”与“让我的生活保持灵活”的斗争的另一章。我猜安德拉斯的答案是最好/最简单但最灵活的方法。
    • 我愿意接受 2 个答案的情况之一!
    【解决方案3】:

    虽然有很多插件可以做这种事情 - 值得注意的是,如果您使用 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;
        }
    
    }
    

    【讨论】:

    • +1:你也可以使用ctrl + . 到达相同的菜单(至少在VS2010 Express中)。
    • 酷 - 这比三键版本容易得多!
    • 这真的很酷。多谢了。不是我所希望的 100%,但正如丹指出的那样,我太专注于我目前的情况,没有考虑很多相关方面。所以我猜是Ctrl+。它是:)
    猜你喜欢
    • 2014-01-12
    • 2023-03-02
    • 1970-01-01
    • 1970-01-01
    • 2015-06-01
    • 1970-01-01
    • 2019-12-24
    • 2011-02-13
    • 2015-02-04
    相关资源
    最近更新 更多