【问题标题】:Why does Resharper think IPrincipal.Identity will never be null?为什么 Resharper 认为 IPrincipal.Identity 永远不会为空?
【发布时间】:2013-12-05 12:26:52
【问题描述】:

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

我假设这是因为 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 的“有用”突出显示...

果然,当您按下 F5 时,程序会抛出异常。我想说这可以回答我原来的问题“因为 Resharper 是错误的”:)

编辑 2: Resharper 错误报告提交至 http://youtrack.jetbrains.com/issue/RSRP-398551

【问题讨论】:

  • “在 VS2010 中运行的 Resharper 8” R# 8 是否适用于 VS2010? jetbrains.com/resharper/documentation/… 如果是这样,我很高兴,因为我认为我无法将它用于 VS2012、VS2010 :)
  • @Dylan 你能打破它吗?如果是,那么这是 Resharpers 部分的错误
  • 你试过你的 FooPrincipal 类了吗? R# 的行为是否与它不同?

标签: c# resharper iprincipal


【解决方案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 属性永远不会为空。 虽然这对于 IPrincipal 的默认 Microsoft 实现可能是正确的,但这并不总是意味着对于像您这样的自定义实现也是如此。

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

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

【讨论】:

    【解决方案2】:

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

    Resharper 无法知道您是否将 "FooPrincipal" 作为参数发送给方法。

    【讨论】:

    • 如果你说的是正确的,那么 Resharper 为什么不将声明 principal != null 标记为过时?
    【解决方案3】:

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

    • 由于IsOverride 是私有的,因此不能(通常)在课堂外调用它
    • 因为没有人调用它,或者它只使用具体实现来调用,例如 GenericPrinciple(参见 https://stackoverflow.com/a/13053981/870604
    • 那么它永远不可能是null

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-09-09
      • 1970-01-01
      • 1970-01-01
      • 2015-01-18
      • 2011-08-04
      • 1970-01-01
      相关资源
      最近更新 更多