为什么Resharper认为IPrincipal.Identity永远不会为空?

时间:2013-12-05 12:26:53

标签: c# resharper iprincipal

在VS2010中运行的Resharper 8告诉我可以删除对principal.Identity != null的检查:

enter image description here

我假设这是因为在IPrincipal的代码中有一个NotNull属性或潜伏的东西,但编写自己的IPrincipal实现很容易返回null身份:

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不会成为我返回null身份的FooPrincipal之一?

编辑:好的,这是一个完整的复制案例,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:http://youtrack.jetbrains.com/issue/RSRP-398551提交的Resharper错误报告

3 个答案:

答案 0 :(得分:2)

我还可以使用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。 虽然对于IPrincipal的默认Microsoft实现可能也是如此,但这并不总是意味着它会适用于像您这样的自定义实现。

我从外部注释文件中删除了上面的行,问题就消失了。

但是我看到您的错误报告导致版本8.2.0.2713的修复,所以它可能会被解决。如果没有,你总是可以从注释文件中删除上面的行,你的问题也应该解决。

答案 1 :(得分:0)

Resharper期望如果执行该方法,参数"IPrincipal principal"不为空,那么在Resharpers Eyes中检查!= null将会过时

Resharper无法知道您是否正在向方法发送"FooPrincipal"参数。

答案 2 :(得分:0)

在更新问题之前并根据您提供的代码片段,可以认为R#足够聪明,可以理解:

  • 由于IsOverride是私有的,因此无法在您的课程外(通常)调用
  • 没有人称之为或只是通过GenericPrinciple等具体实施来调用(见https://stackoverflow.com/a/13053981/870604
  • 然后它不可能是null

现在,如果您同时发出警告和NullReferenceException,可以认为它是R#中的错误。