是否有更好的方法将 Enumerable.Range 的结果转换为 Double?

Is there a nicer way to Cast the result of Enumerable.Range to type Double?

要制作从 1 到 10 的双精度数组,我目前正在做:

Dim N() As Double = Enumerable.Range(1, 10).Select(Function(x) CDbl(x)).ToArray

我的技术似乎效率低下且间接。我看到 ToArray 有 space 作为参数,但每当我尝试 ToArray(Double)ToArray(Of Double) 时,它都会给我一个错误。

通过Enumerable.Range创建数组时,将元素转换为 Double 类型的正确方法是什么?

如果您的长度有限并且事先知道数字,最有效的方法是创建具有上限的数组并单独设置项目。当您明确指定时,编译器不需要推断上限:

Dim n(9) As Double
n(0) = 1
n(1) = 2
'etc...

' or even more concise
For counter As Integer = 1 To 0
    n(counter - 1) = counter
Next

另一种方法是创建具有显式初始化的数组。这是“性能较低”,因为编译器必须推断上限,但我认为这是一个边际性能损失:

Dim n() As Double = { 1, 2, 3, 4, 5, 6, 7, 8, 9 }

如果您不想输入值,那么您可以做您正在做的事情并创建一个范围,然后转换结果。使用 Select 的替代方法是使用 ConvertAll 方法:

Dim n() As Double = Array.ConvertAll(Enumerable.Range(1, 10).ToArray(), Function(counter) Convert.ToDouble(counter))

长话短说,你所做的并没有错。如果您追求性能,这不是最佳解决方案,但通常情况下您应该没问题。

有没有更好的方法...

好吧,更好 是相对的 - 但相对于哪种质量?如果性能就是质量,那么请避免使用 LINQ。如果简单就是质量,那么使用 LINQ。

Dim count = 1000000

Dim sw As New Stopwatch()

sw.Start()
Dim n = Enumerable.Range(1, count).Select(Function(x) CDbl(x)).ToArray()
sw.Stop() 
Console.WriteLine(sw.ElapsedMilliseconds)

sw.Restart()
Dim m(count - 1) As Double
For i = 0 To m.GetUpperBound(0)
    m(i) = CDbl(i + 1)
Next
sw.Stop() 
Console.WriteLine(sw.ElapsedMilliseconds)

35
6

显然,一个更干净,另一个更快。哪一个更好取决于你...