【问题标题】:What happens when I cast null to another class当我将 null 转换为另一个类时会发生什么
【发布时间】:2016-03-03 11:51:01
【问题描述】:

我在一个库方法中有一些代码,如下所示:

public static WebDavProviderBase GetProvider(string relativePath)
{
  if (relativePath == null)
    return (WebDavProviderBase) null;
  if (relativePath.Length == 0)
    return (WebDavProviderBase) new DefaultProvider();
  WebDavProviderBase returnProvider = (WebDavProviderBase) null;
  if ((int) relativePath[0] == 47)
    relativePath = relativePath.Substring(1);
  WebDavProviderBase.GetRootProvider().MapPath(relativePath, out returnProvider);
  return returnProvider;
}

当我使用代码时,它看起来像这样:

WebDavProviderBase provider = WebDavProviderBase.GetProvider(relativePath);

if (provider == null)
{
    //Do something
}

但是,Resharper (10 Ultimate) 抱怨 null 检查,并说这是一个多余的检查,因为 provider 永远不能为 null。

Resharper 是不是错了,还是 (WebDavProviderBase)null 会返回一个新的 WebDavProviderBase?

按要求截图:

更新: 从下面的 Jebs 回答中得到帮助后,这是结论: 当 GetProvider 被调用时,relativePath 不能为空,因为应用程序已经崩溃,因为代码中的 relativePath.Lenght 进一步检查。 (见截图)

【问题讨论】:

  • 重塑器错误。或者您发布的代码过于简化。请注意,我没有收到 Resharper 警告(我使用的是 R#10.0.2)。所以我怀疑你没有发布正确的复制品。
  • 我已经用完整的第三方库代码更新了这个问题,以防它产生任何影响。另请注意,此代码位于第三方 dll 中。
  • 刚刚意识到不是 Resharper 给出了错误,而是 Visual Studio 2015 Professional。再次更新问题。
  • 如果你改写WebDavProviderBase.GetProvider(null);会发生什么?
  • 请发布您收到的完整错误消息。另外,如果可能,请提供一个minimal reproducible example,它只使用我们有权访问的类。

标签: c# resharper


【解决方案1】:

让我们从解决您的结论性问题开始。其中有两个,合并为一个(请尽量避免),所以我将它们分开并一次回答一个:

Resharper 错了吗...?

是的。好吧,也许……稍后会详细介绍。

... 还是(WebDavProviderBase)null 会返回一个新的 WebDavProviderBase?

没有。


Visual Studio 2015 Professional ... 说这是一个多余的检查,因为 provider 永远不能为空。

这可能只是巧合地与您提出的问题有关,但无论如何解释我认为这里发生的事情可能会有所帮助。 VS2015 可能在进行某种形式的推演,推断当relativePath 为非空时,返回值也将为非空。这里有两个先决条件:

  • VS2015 是否可以仅通过查看您编写的代码就推断出relativePath 是非空的?例如,如果您已将其分配给一个常数值,则答案是肯定的“是”。 更新.ToString() 方法保证返回字符串或引发异常,因此编译器很可能推断出relativePath 在此处始终为非空。
  • VS2015 能否推断出非空relativePath 值对应非空GetProvider 返回值?这代表编译器涉及更复杂的功能,但它并不超出编译范围......如果编译器可以遵循您的逻辑并推断出不可能返回null,那么它可以安全地告诉您你的null 检查是错误的。

【讨论】:

  • 我试图追踪 relativePath 的创建,但我无法真正到达真正创建的结尾。
  • @andreasnico 推论不仅基于值,还基于运算...例如,如果在relativePath 上使用了任何String 方法(例如String.Length)在调用WebDavProviderBase.GetProvider 之前,这样的推断就足够了,因为此时会抛出异常,在调用方法之前中断执行。
  • 啊,所以 relativePath.Length(最近添加的截图)当然会在调用 GetProvider 之前使整个事情崩溃,因此调用 GetProvider 时 relativePath 不能为空。谢谢!
  • ...即使他们这样做了,编译器也会注意到该方法被覆盖并相应地调整它的扣除。
  • @andreasnico 确实。我的错... this.RemoveTrailingSlash 中可能使用了字符串方法(或数组索引),如果 request.Pathnull 时会抛出异常...也许您可以添加一些 null 检查和 return null 到那,看看这会如何改变事情?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-10-07
  • 2014-04-12
  • 1970-01-01
  • 1970-01-01
  • 2021-05-07
  • 2012-09-10
  • 2018-05-16
相关资源
最近更新 更多