关于c#:为什么Resharper认为IPrincipal.Identity永远不会为null?

Why does Resharper think IPrincipal.Identity will never be null?

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

enter image description here

我假设这是因为IPrincipal的代码中存在NotNull属性或某些内容,但是编写自己的IPrincipal实现返回一个空的Identity很容易:

1
2
3
4
5
6
7
8
9
10
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之一?

编辑:好的,这是一个完整的复制案例,其中Resharper实际上鼓励您编写在生产中爆炸的代码...

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
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错误报告


我还可以在VS2010和R#7.1(使用.NET Framework 4.0)中重现此内容。

这是由Resharper的外部注释引起的。由于某种原因,您可以在文件中找到以下语句:

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

1
2
3
  <member name="P:System.Security.Principal.IPrincipal.Identity">
   
  </member>

这说明任何IPrincipal.Identity属性都绝不会为null。
尽管对于IPrincipal的默认Microsoft实现可能是这样,但这并不总是意味着对于像您这样的自定义实现也是如此。

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

但是我看到您的错误报告对8.2.0.2713版本进行了修复,因此可以解决该问题。如果不是这样,您总是可以从注释文件中删除上面的行,您的问题也应该得到解决。


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

  • 由于IsOverride是私有的,因此不能(通常)在您的课程之外调用
  • 没有人称其为OR,或者仅通过诸如GenericPrinciple之类的具体实现来调用它(请参阅https://stackoverflow.com/a/13053981/870604)
  • 那么它永远不可能是null

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


Resharper期望,如果执行该方法,则参数"IPrincipal principal"不为null,因此在Resharpers Eyes中将不检查!= null

Resharper不知道您是否要向该方法发送"FooPrincipal"作为参数。