【问题标题】:Dependency Injection and C# syntax依赖注入和 C# 语法
【发布时间】:2009-03-23 07:30:13
【问题描述】:

我想知道是否有人可以解释这个sn-p的一行中的语法 代码:

public class ContactController : Controller
{
    private IContactManagerRepository _repository;

    **public ContactController()
        : this(new EntityContactManagerRepository())**
    {}


    public ContactController(IContactManagerRepository repository)
    {
        _repository = repository;
    }

我特别感兴趣的是第一个构造函数。我 从我得到它的文章中了解 (http://www.asp.net/learn/mvc/tutorial-29-cs.aspx - 清单 3) 第一个构造函数调用第二个构造函数,当我悬停时智能感知会告诉我 在它确实引用的 this(new EntityContactManagerRepository()) 之上 第二个构造函数。但是我没有看到后面有冒号的构造函数 它之前。我知道类声明中的冒号告诉 ContactController 从 Controller 继承的编译器,但是 构造函数中的冒号呢?

【问题讨论】:

    标签: c# model-view-controller


    【解决方案1】:

    正如你所说,它只是调用另一个构造函数作为执行的第一部分。另一种方法是使用base,它调用基类中的构造函数。语言规范为此调用使用术语构造函数初始化器总是 是这样的 - 如果您不指定任何内容,则相当于调用 base()。换句话说:

    public Foo(int x)
    

    等价于

    public Foo(int x) : base()
    

    在这两种情况下,基类的无参数构造函数都会在 Foo 构造函数的主体执行之前调用。编译器确保您不会陷入无限循环——每个(非静态)类必须至少有一个调用基类构造函数的构造函数;你总是在“this”类的构造函数体执行之前调用基类构造函数。

    然而,与 Java 不同的是,实例变量初始值设定项在基类构造函数调用之前执行。

    请查看我的article about constructor chaining 了解更多信息。

    【讨论】:

      【解决方案2】:

      它被称为constructor chaining。使用该语法,您可以调用基类的构造函数或当前类的另一个构造函数。

      【讨论】:

        【解决方案3】:

        此功能称为Constructor Initializers

        【讨论】:

          【解决方案4】:

          您的示例使用构造函数链接。 IE。默认构造函数调用具有相同类型参数的特定构造函数。为此,您可以将 this 关键字与示例中所需的任何参数一起使用。

          类似的功能是使用base 关键字。当你有一个类层次结构时,你总是为层次结构中的所有类型调用构造函数。因此,例如,如果您有一个B 类和一个D 类,当您创建D 的实例时,您将调用B 的构造函数,然后调用D 的构造函数。对于默认构造函数(即没有参数),您无需执行任何操作。但是,如果B 只实现了一个需要参数的构造函数,则需要某种方法从D 的构造函数中传递它。为此,您可以使用类似于在您的示例中使用 this 的方式的 base 关键字。

          【讨论】:

            【解决方案5】:

            这是缺少可选/默认参数支持的结果(解决方法)。您可能会遇到以下情况:

            MessageBox.Show(string)
            ...
            MessageBox.Show(Window, string, string)
            ...
            MessageBox.Show(Window, string, string, MessageBoxButton, MessageBoxImage, MessageBoxResult, MessageBoxOptions)
            

            在这些情况下,通常具有最多参数的那个包含一个实现,而其他重载只是使用默认参数调用那个。需要注意的一点是,当参数数量增加到 N 时,重载的数量可能会增加到 N!。

            构造函数是特殊功能,因此您必须以应有的方式对待它们。一个对象只能构造一次。请记住,在普通函数中,您可以多次调用实现函数。在这里,您必须调用一次构造函数,这也是要做的第一件事。构造函数链接语法指出了这些要求。

            让我们回到最初的问题。尽管这些情况并不常见,但您可以通过定义一个新类型(这里使用 C# 3.0 特性)来解决这个问题,该类型将用作参数:

            public class Parameter
            {
                public string P1 { get; set; }
                public int P2 { get; set; }
                public string P3 { get; set; }
                public double P4 { get; set; }
                ...
                public Parameter()
                {
                    P1 = "p1";
                    P2 = 2;
                    P3 = "p3";
                    P4 = 4.0;
                    ...
                }
            }
            ...
            FunctionWithManyParametersCanNowBeCalledLike(new Parameter() { P2 = -2 });
            

            这里我们在构造函数中提供了默认参数。这是许多构造函数的解决方案吗?没有。

            C# 4.0 将包含可选参数和命名参数功能。所以我们甚至不需要定义一个新的参数类型。您可能会认为该功能是为此的语法糖,但是它们有所不同。对于基类构造函数参数,我们仍然需要这种语法。

            【讨论】:

              【解决方案6】:

              冒号用于表示您正在调用同一类中的另一个构造函数(如您的示例中)或使用:base(..args...) 的基类中的构造函数

              此语法用于强制您在执行任何额外工作之前调用其他构造函数或基构造函数(即,它确保基类首先初始化顺序)。

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 2011-07-14
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2021-11-19
                • 2010-10-31
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多