Скажем, у меня есть один интерфейс и два класса, и один из классов реализует этот интерфейс:

interface IAAA
{
    int F1 { get; set; }
}

class AAA1
{
    public int F1 { get; set; }
    public int F2 { get; set; }
}

class AAA2 : IAAA
{
    public int F1 { get; set; }
    public int F2 { get; set; }
}

В классе AAA2 свойство F1 «наследуется» (я не уверен) от интерфейса IAAA, затем я использую отражение, чтобы проверить, является ли свойство виртуальным:

Console.WriteLine("AAA1 which does not implement IAAA");
foreach (var prop in typeof(AAA1).GetProperties())
{
    var virtualOrNot = prop.GetGetMethod().IsVirtual ? "" : " not";
    Console.WriteLine($@"{prop.Name} is{virtualOrNot} virtual");
}

Console.WriteLine("AAA2 which implements IAAA");
foreach (var prop in typeof(AAA2).GetProperties())
{
    var virtualOrNot = prop.GetGetMethod().IsVirtual ? "" : " not";
    Console.WriteLine($"{prop.Name} is{virtualOrNot} virtual");
}

Результат:

AAA1 which does not implement IAAA
F1 is not virtual
F2 is not virtual
AAA2 which implements IAAA
F1 is virtual
F2 is not virtual

По какой причине?

39
runerback 27 Ноя 2018 в 06:58

1 ответ

Лучший ответ

Начиная с замечаний раздел документов MS:

Виртуальный член может ссылаться на данные экземпляра в классе, и на него следует ссылаться через экземпляр класса ... Среда CLR требует, чтобы все методы, реализующие элементы интерфейса, были помечены как виртуальные; поэтому компилятор помечает метод virtual final

Если вам нужно определить, является ли этот метод переопределяемым, тогда проверки IsVirtual недостаточно, и вам также необходимо проверить, что IsFinal ложно.

Вот метод расширения, который выполняет эту проверку:

public static bool IsOverridable(this MethodInfo method)
    => method.IsVirtual && !method.IsFinal;
33
Alexei Levenkov 27 Ноя 2018 в 07:00