Почему Resharper считает IPrincipal.Identity никогда не будет нулевым?

Resharper 8, работающий в VS2010, говорит мне, что я могу удалить проверку для principal.Identity != null:

enter image description here

Я предполагаю, что это связано с тем, что атрибут NotNull или что-то скрывается в коде для IPrincipal, но довольно легко написать собственную реализацию IPrincipal, которая возвращает null Identity:

void Main() {
    var foo = new FooPrincipal();
    Console.WriteLine(foo.Identity == null ? "Yep!" : "Not Null");
}

class FooPrincipal : IPrincipal {
    public IIdentity Identity { get; set; }
    public bool IsInRole(string role) { return(false); }
    public FooPrincipal() {}
}

Как может Resharper знать, что IPrincipal, переданный в этот метод, не будет одним из моих FooPrincipals, которые возвращают нулевые идентификаторы?

EDIT: Хорошо, здесь полный случай воспроизведения, где Resharper на самом деле побуждает вас писать код, который взрывается в процессе производства...

using System;
using System.Security.Principal;

namespace ResharperPrincipalTest {
    class Program {
        static void Main(string[] args) {
            var p = new TestPrincipal();
            var isJeff = IsUserCalledJeff(p);
            Console.WriteLine(isJeff);
        }

        static bool IsUserCalledJeff(IPrincipal principal) {
            if (principal != null) {
                if (principal.Identity == null) throw(new Exception("Resharper says this will never happen!"));
                return (principal.Identity.Name == "jeff");
            }
            return false;
        }
    }

    class TestPrincipal : IPrincipal {
        public bool IsInRole(string role) {
            return (false);
        }

        public IIdentity Identity { get; set; }
    }
}

и скриншот от VS2010, показывающий "полезную" подсветку Resharper...

enter image description here

и, конечно, когда вы нажмете F5, программа выдает исключение. Я бы сказал, что это ответ на мой оригинальный вопрос "потому что Resharper ошибочен":)

РЕДАКТИРОВАТЬ 2: Отчет об ошибках Resharper, поданный на http://youtrack.jetbrains.com/issue/RSRP-398551

Ответ 1

Я также могу воспроизвести это с помощью VS2010 и R # 7.1 (с использованием .NET Framework 4.0)

Это вызвано внешними аннотациями Resharper. По какой-то причине вы можете найти в файле следующую инструкцию:

Resharper_Install_Folder\v7.1\Bin\ExternalAnnotations.NETFramework\mscorlib\4.0.0.0.Contracts.xml

  <member name="P:System.Security.Principal.IPrincipal.Identity">
    <attribute ctor="M:JetBrains.Annotations.NotNullAttribute.#ctor" />
  </member>

Это означает, что любое свойство IPrincipal.Identity никогда не будет равно NULL. Хотя это может быть правдой для реализаций Microsoft по умолчанию для IPrincipal, это не всегда означает, что это будет верно для пользовательских реализаций, подобных вашим.

Я удалил строки из внешнего файла аннотаций, и проблема исчезла.

Но я вижу, что ваш отчет об ошибке привел к исправлению для версии 8.2.0.2713, поэтому он может быть решен этим. Если нет, вы всегда можете удалить строки из файла аннотаций, и ваша проблема также должна быть решена.

Ответ 2

Resharper ожидает, что если метод будет выполнен, параметр "IPrincipal principal" не является нулевым, поэтому проверка на!= null будет устаревать в Resharpers Eyes

Resharper не может знать, отправляете ли вы параметр "FooPrincipal" как метод.

Ответ 3

Перед обновлением вашего вопроса и на основе кода, который вы указали, можно подумать, что R # достаточно умен, чтобы понять это:

  • Поскольку IsOverride является закрытым, его нельзя вызвать (обычно) вне вашего класса
  • Поскольку никто не называет его ИЛИ он вызван только с конкретной реализацией, такой как GenericPrinciple (см. fooobar.com/info/326649/...)
  • Тогда это никогда не может быть null

Теперь, если вы можете создать предупреждение и NullReferenceException, можно предположить, что это ошибка в R #.