2014-01-23 3 views
-1

Я хотел бы спросить, каковы риски, имеющие что-то следующим образом:вызова абстрактный метод из абстрактного класса конструктора

abstract public class HtmlTemplateBuilder 
{ 
    HtmlSource source; 

    protected HtmlTemplateBuilder() 
    { 
     LoadTemplates(); 
    } 

    public abstract void LoadTemplates(); 
} 

риск, если производный класс является производным от производного класса:

DerivedClass2 -> # DerivedClass1 -> HtmlTemplateBuilder

Это можно решить, запечатав # DerviedClass1, но есть ли какие-либо риски или более эффективные методы для реализации этой функции?

Благодаря

+1

Какой риск вы видите в своем примере? Можете быть более конкретными ? –

+0

Resharper говорит (и я понимаю почему): вызов виртуального участника в конструкторе. –

ответ

1

Посмотрите на этой ссылке, которая объясняет опасности с простым легко понять примеры

https://blogs.msmvps.com/peterritchie/2012/04/25/virtual-method-call-from-constructor-what-could-go-wrong/

Я хотел бы удалить вызов LoadTemplates из конструктора и называю Initialise на нем, когда в шаблоны должны быть загружены и использованы.

abstract public class HtmlTemplateBuilder 
{ 
    HtmlSource source; 
    object locker = new object(); 
    private bool initialised; 

    protected HtmlTemplateBuilder() 
    { 
    } 

    protected void Initialise() 
    { 
     lock (locker) 
     { 
      if(initialised) 
      { 
       LoadTemplates(); 
       initialised = true; 
      } 
     } 
    } 

    public abstract void LoadTemplates(); 
} 
+0

Это более или менее тот риск, который я объяснил, в моем примере ответственность за реализацию лежит на производном классе. Я попросил лучших/альтернативных решений, которые не являются рискованными. –

+0

Я бы использовал ленивые шаблоны загрузки. Не только это снижает вероятность того, что кто-то может снова включить риск в будущем, изменив ваши классы, он также сохранит объекты в легком до момента фактического использования. В первой точке, где вам нужны шаблоны для загрузки, проверьте, загружены ли они, сохраняя состояние в булевом флаге, иначе загрузите. –

+0

Я отредактировал свой ответ, чтобы проиллюстрировать, что я имею в виду. –

1

Ситуация, в которой эта картина укусила меня выглядят следующим образом: на более позднем этапе вы хотите добавить специализированный HtmlTemplateBuilder, который может загружать различные шаблоны на основе некоторых критериев, неизвестных сам класс (может быть, вы решите, что вам хотите некоторые классные шаблоны в определенный день года). То есть:

public class SpecialHtmlTemplateBuilder : HtmlTemplateBuilder 
{ 
    private bool someCondition; 

    public override void LoadTemplates() 
    { 
     if (someCondition) 
     { 
      LoadTemplatesSet1(); 
     } 
     else 
     { 
      LoadTemplatesSet2(); 
     } 
    } 
} 

Но как вы собираетесь передать someCondition классу? Ниже не будет работать:

public class SpecialHtmlTemplateBuilder : HtmlTemplateBuilder 
{ 
    private bool someCondition; 

    public SpecialHtmlTemplateBuilder (bool someCondition) 
    { 
     this.someCondition = someCondition; 
    } 

    // ... 
} 

, поскольку назначение this.someCondition будет сделано после вызова базового конструктора, т.е. послеLoadTemplates() называются. Обратите внимание, что производные классы уплотнения не решить эту проблему.

Способ решения проблемы описан в следующем виде: добавить явный метод Initialize и вызвать его после конструктора.

Смежные вопросы