【问题标题】:Can the result of as operator be null if the is operator returns true?如果is运算符返回true,as运算符的结果可以为null吗?
【发布时间】:2014-11-17 19:43:43
【问题描述】:

我正在使用代码质量工具,他们说我可以在第 3 行采用以下块样式:

1    if(var1 is Type1)
2    {
3         (var1 as Type1).methodCall();
4    }

建议进行以下更改:

1    Type1 tempVar = var1 as Type1; 
2    if(tempVar != null)
3    {
4         tempVar.methodCall();
5    }

这将如何改变可能出现 null 尊重异常的情况?根据 msdn,如果“提供的表达式不为空,并且提供的对象可以转换为提供的类型而不会引发异常”,则将返回 true。 (http://msdn.microsoft.com/en-us/library/scekt9xw.aspx)

var1 is Type1 的计算结果为 True,但 var1 as Type1 的计算结果为 null。或者这是不可能的,只是代码质量工具的限制。

我正在使用 jetbrains re-sharper 和 hp fortify。

【问题讨论】:

  • 请注意,第二个代码还修复了某些工具发出的“避免重复调用as”警告,因此您可能只想坚持下去。
  • 除了下面的 servy 回答之外,还有一个(有点理论上的)性能问题。在内部,isas 运算符在做同样的事情(对于引用类型),那么为什么要这样做两次呢? (编辑:就像阿列克谢刚才说的一样)
  • @KrisVandermotten 不过,这在很大程度上是一个微优化。这根本不是一项昂贵的手术。
  • 性能这件事是一个因素,一个小因素。我确实喜欢它的可读性,但很多时候在 if else if ... 中有多个 var is 类型调用会阻塞并使它变得丑陋。
  • @Servy 就像我说的,有点理论上的性能问题。在实践中,它几乎不会被检测到,即使在一个紧密的循环中也是如此。

标签: c# casting


【解决方案1】:

您的第一个程序抛出 NRE 的唯一方法是,var1 可能在检查之后和方法调用之前从另一个线程发生变异。假设您不需要协调来自另一个线程的突变(或已经有适当的同步),这是代码分析工具的误报,您的原始代码不会抛出 NRE。

【讨论】:

  • 强制警告,在多线程场景和非常糟糕的代码中,tempVar 在检查后确实可能为 null,但这不太可能。
  • @Servy 谢谢,这听起来不错。我想确保我没有遗漏任何东西。大多数这些情况在发生线程的地方都没有。
  • +1。另一个明显的可能性是Type1 var1 {get {return count++ == 0 ? null : someValue;},但可能并非如此(顾名思义就是局部变量)。
【解决方案2】:

如果另一个线程可以访问var1 的值,它可能会在isas 之间变化。

即使在您的特定情况下不太可能,甚至不可能,建议的代码也完全不受此类更改的影响,因此这是一种很好的做法。

建议的代码也只进行一次类型检查,因此它的性能甚至稍微好一些。即使性能差异并不总是很显着,但这仍然意味着您可以免费获得更好的代码。

【讨论】:

    猜你喜欢
    • 2020-05-12
    • 2021-05-12
    • 1970-01-01
    • 2023-04-05
    • 1970-01-01
    • 2017-10-23
    • 2013-08-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多