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

640 views Asked by At

Resharper 8 running in VS2010 is telling me I can remove a check for principal.Identity != null:

enter image description here

I'm assuming this is because there's a NotNull attribute or something lurking in the code for IPrincipal, but it's quite easy to write your own IPrincipal implementation that returns a 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() {}
}

How can Resharper know that the IPrincipal passed into this method isn't going to be one of my FooPrincipals that return null identities?

EDIT: Ok, here's a full reproduction case where Resharper actually encourages you to write code that blows up in production...

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; }
    }
}

and the screenshot from VS2010 showing Resharper's 'helpful' highlighting...

enter image description here

and sure enough, when you hit F5 the program throws an exception. I'd say that makes the answer to my original question "because Resharper is wrong" :)

EDIT 2: Resharper bug report filed at http://youtrack.jetbrains.com/issue/RSRP-398551

3

There are 3 answers

1
JvRossum On

Resharper expects that if the method is executed the Parameter "IPrincipal principal" is not null, so a check for !=null would be absolete in Resharpers Eyes

Resharper can't know if you are sending a "FooPrincipal" as parameter to the Method.

0
ken2k On

Before the update to your question and based on the piece of code you provided, one can think R# was smart enough to understand that:

  • As IsOverride is private, it can't be called (normally) outside your class
  • As no one calls it OR it's only called with a concrete implementation such as GenericPrinciple (see https://stackoverflow.com/a/13053981/870604)
  • Then it can't ever be null

Now, if you can produce both a warning and a NullReferenceException, one can assume it's a bug in R#.

0
Huron On

I can also reproduce this with VS2010 and R# 7.1 (using .NET Framework 4.0)

This is caused by Resharper's external annotations. For some reason you can find the following statement in the file :

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>

What this states is that any IPrincipal.Identity property will NEVER be null. While this might be true for the default Microsoft implementations of IPrincipal, this does not always mean it will be true for custom implementations like yours.

I removed the lines above from the external annotations file and the problem goes away.

But I see your bug report resulted in a fix for version 8.2.0.2713, so it might be solved by that. If not you can always remove the lines above from the annotations file and your problem should also be solved.