2013-11-12 4 views
0

Лучшей практикой является не вызов виртуальных функций из конструктора базовых классов (предупреждение появляется в FxCop или Sonar), однако как насчет классов, которые не предназначены для использования в качестве базовых классов, но имеют виртуальные методы для насмешек. Является ли этот случай, когда я должен использовать файл GlobalSuppressions, или есть способ издеваться над методом, который вызывается в конструкторе, не будучи виртуальным?Вызов виртуальных функций от конструктора и насмешка

Вот код, чтобы уточнить:

public class MyClass 
{ 
    public MyClass() 
    { 
     MyVirtualMethod(); 
    } 
    private virtual void MyVirtualMethod() { } 
} 

MyVirtualMethod виртуален для насмешливых только.

ответ

0

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

Таким образом, ваш виртуальный метод не будет виртуальным.

Ниже приведен пример из C++ FAQ, перекодированного в C#.

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 

namespace VirtualMethodCalledFromConstructor 
{ 

    class Program 
    { 
     static void Main(string[] args) 
     { 
      Derived d = new Derived(); 
      Console.ReadLine(); 
     } 
    } 

    public class Base 
    { 
     public Base() 
     { 
      Console.WriteLine("Base::Base()"); 
      virt(); 
     } 
     public virtual void virt() 
     { 
      Console.WriteLine("Base::virt()"); 
     } 
    } 

    public class Derived : Base 
    { 
     public Derived() 
     { 
      Console.WriteLine("Derived::Derived()"); 
      virt(); 
     } 

     public virtual void virt() 
     { 
      Console.WriteLine("Derived::virt()"); 
     } 
    } 
} 

Это производит следующий вывод в консоли:

Base::Base() 
Base::virt() // <--- not Derived::virt() 
Derived::Derived() 
Derived::virt() 

Обратите внимание, что «Derived :: Вирт()» только который вызывается, потому что производный конструктор явно назвал его.

+0

Идея состоит в том, чтобы переопределить virt() в производном классе, однако мы не получаем непосредственно из класса. Функция виртуальна только для насмешливых целей. Проблема, о которой предупреждают, состоит в том, что можно вызвать функцию на производном классе из базового класса до выполнения конструктора производных классов. Но поскольку мы ничего не наследуем, это не должно быть проблемой, иначе это ложное предупреждение. – ConditionRacer

+0

По-видимому, я делал неправильное предположение о вашем издевательстве. Я предположил, что вы хотели заменить реализацию определенного метода «virt()». Если я правильно вас понимаю, вы используете насмешливый инструмент, который будет генерировать макет класса «Derived» с тем же интерфейсом, что и «Base», но который на самом деле не наследуется от «Base». Если это правильно, я не понимаю, почему ваш издевательский инструмент требует от вас использовать «виртуальное» ключевое слово. Кажется, неправильно. – Hezi

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