【问题标题】:Why Array.zeroCreate still fills null for non nullable type?为什么 Array.zeroCreate 仍然为不可为空的类型填充 null?
【发布时间】:2012-12-03 19:09:27
【问题描述】:

这是否意味着每当我传递一个不可为空类型的数组时,我仍然应该检查它是否为空?实际上甚至不可能检查<> null,而是必须使用operator.unchecked。它比C#更好吗?

type test=
    {
        value: int
    }

let solution = Array.zeroCreate 10

solution.[0] <- {value = 1}
solution.[1].value   // System.NullReferenceException: Object reference not set to an instance of an object

type test =
  {value: int;}
val solution : test [] =
  [|{value = 1;}; null; null; null; null; null; null; null; null; null|]
val it : unit = ()

【问题讨论】:

    标签: f#


    【解决方案1】:

    正如Array.zeroCreate 的文档所示,它将元素初始化为Unchecked.defaultof&lt;_&gt;。因此,这带有与直接使用 Unchecked.defaultof 相同的所有警告。一般来说,我的建议是尽可能使用Array.create/Array.init,并将Array.zeroCreate 视为可能的性能优化(在处理不可为空的类型时需要小心)。

    【讨论】:

      【解决方案2】:

      这取决于从哪里传递数组。

      如果数组只在F#中创建和使用,那么不,你不需要检查null;实际上,您不应该检查 null(使用 Unchecked.defaultOf),因为 F# 编译器优化了一些特殊值,例如 [](和 None,在某些情况下)通过将它们表示为 @ 987654325@在编译的IL中。

      如果您正在使用由另一种语言(例如 C#)编写的代码传入的数组,那么是的,您仍然应该检查 null。如果调用代码只是创建数组并且没有进一步改变它,那么您只需要执行一次 null 检查。

      编辑:这是先前关于 F# 编译器如何使用 null 优化某些值的表示的讨论:Why is None represented as null?

      【讨论】:

      • 即使我只在 F# 中使用,例如解决方案。[1].value 会引发 System.NullReferenceException: Object reference not set to an instance of an object.
      • 您是调用 Array.zeroCreate 的人。因此,在将数组暴露给可能会出现 NullReferenceException 的其他代码之前填充数组,这不是问题。
      【解决方案3】:

      您正在创建一个记录类型,它被实现为一个类,它确实可以为空。如果您打算创建一个结构,您的代码应如下所示:

      type test =
          struct
              val value: int
              new(v) = { value = v }
              override x.ToString() = x.value.ToString()
          end
      
      let solution = Array.zeroCreate 10
      
      solution.[0] <- test(1)
      

      这个输出:val solution : test [] = [|1; 0; 0; 0; 0; 0; 0; 0; 0; 0|]

      您还可以使用 Struct 属性编写类型,从而节省一定程度的缩进。

      [<Struct>]
      type test =
          val value: int
          new(v) = { value = v }
          override x.ToString() = x.value.ToString()
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-08-03
        • 2016-09-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-06-26
        • 2017-05-12
        • 2020-01-22
        相关资源
        最近更新 更多