2009-03-23 7 views
2

Интересно, если кто-нибудь может объяснить синтаксис в одной строке этого фрагмент кода :Dependency Injection и C# синтаксис

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), что первый конструктор вызывает второе, и IntelliSense говорит мне, когда я парить над этим (новый EntityContactManagerRepository()), что это действительно означает второй конструктор. Но я еще не видел конструктора с двоеточием после . Я знаю, что двоеточие в объявлении класса сообщает компилятору , что ContactController наследует от Controller, но что делает двоеточие в конструкторе?

ответ

5

Как вы уже сказали, он просто вызывает другой конструктор в качестве первой части исполнения. Альтернативой является использование base, который вместо этого вызывает конструктор в базовом классе. Спецификация языка использует для этого вызова термин инициализатор конструктора . Там всегда что-то вроде этого - если вы ничего не укажете, это эквивалентно вызову base(). Другими словами:

public Foo(int x) 

эквивалентно

public Foo(int x) : base() 

В обоих случаях конструктор без параметров базового класса вызывается перед тело Foo конструктору выполняется. Компилятор гарантирует, что вы не попадаете в бесконечный цикл - каждый (нестатический) класс должен иметь по крайней мере один конструктор, который вызывает конструктор базового класса; вы всегда вызываете конструктор базового класса до того, как тело конструктора будет выполняться для этого класса.

В отличие от Java, инициализаторы переменных экземпляра - это, выполняемые перед вызовами конструктора базового класса.

Для получения дополнительной информации см. Мой article about constructor chaining.

3

Это называется constructor chaining. С помощью этого синтаксиса вы можете вызвать конструктор базового класса или другого конструктора текущего класса.

0

Двоеточие используется, чтобы указать, что вы вызываете другой конструктор из того же класса (как в вашем примере) или конструктор базового класса с использованием :base(..args...)

Этот синтаксис используется для обеспечения, что вы вызывая другие конструкторы или базовые конструкторы, прежде чем выполнять какую-либо дополнительную работу (т.е. он обеспечивает первый порядок инициализации базового класса).

1

В примере используется цепочка конструкторов. То есть конструктор по умолчанию вызывает конкретный конструктор с аргументом того же типа. Для этого вы используете ключевое слово this с любыми аргументами, как в вашем примере.

Аналогичная функция - использование ключевого слова base. Когда у вас есть иерархия классов, вы всегда вызываете конструкторы для всех типов в иерархии.Например, если у вас есть класс B и класс D, вы вызываете конструктор B, а затем создаете конструктор D при создании экземпляра D. Для конструкторов по умолчанию (т. Е. Без аргументов) вам не нужно ничего делать. Однако, если B реализует только конструктор, который требует аргумента, вам нужно каким-то образом передать это из конструктора D. Для этого вы используете ключевое слово base, аналогичное тому, как в вашем примере используется this.

1

Это результат (обходной путь) отсутствия опциональной поддержки параметров по умолчанию. Вы можете найти себя в таких ситуациях, как:

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 будет включать в себя необязательные и именованные параметры. Поэтому нам даже не нужно будет определять новый тип параметра. Вы можете подумать, что эта функция является синтаксическим сахаром для этого, однако они различаются. Нам будет по-прежнему нужен этот синтаксис для базовый класс параметры конструктора.