我有一些.Net代码,其测试都是在Mono上传递的,但是一旦我在.Net Core上运行它,一些测试失败了。我最终将失败的测试追溯到他们的根本原因,并发现了一些相当好奇的东西,我想在这里询问哪些更有经验的.Net程序员可以帮助我。
本质上,失败的根本原因是我将类型A的空数组复制到类型B的目标数组中。(我将不会解释为什么我正在复制一个空数组,这样你就不必经历一页又一页的代码。它使代码更简单;大多数时候源数组是B类,但有时创建代码会创建一个A类型的空数组。 Mono说“哦,数组是空的,所以我不会抛出类型错误”,副本成功了。但是,当我在.Net Core上运行测试时,将类型A的空数组复制到类型B的目标数组中会抛出System.ArrayTypeMismatchException
并显示以下消息:
无法将源数组类型分配给目标数组类型。
以下是一些代码,以便我可以向您展示我在代码而不是英语中的含义。 (特别是在F#代码中,因为当我遇到Mono和.Net Core之间的这个有趣区别时,这就是我正在使用的语言。)
let someStrs : string[] = [|"a"; "b"; "c"|]
let someInts : int[] = Array.zeroCreate 3
someStrs.CopyTo(someInts, 0)
对于那些没有很好地阅读F#的人来说,第一行创建了一个包含三个字符串的数组,正如你可能想到的那样。 (F#使用[|
和|]
来声明数组,因为[
和]
括号具有定义单链表的含义。)第二行创建一个数组三个整数,初始化为默认值。对于0的int,所以这会创建数组[|0; 0; 0|]
,但如果我说let someStrs : string[] = Array.zeroCreate 3
,那么结果数组将为[|null; null; null|]
。
该代码自然会失败:您无法将字符串数组复制到整数数组中。它在Mono和.Net Core上都失败了。但现在看看这个:
let someStrs : string[] = [||]
let someInts : int[] = Array.zeroCreate 3
someStrs.CopyTo(someInts, 0)
与以前相同的代码,只是这次我将someStrs
定义为空数组,一个长度为0的数组。它仍然具有类型string[]
,所以将它复制到类型为int[]
的数组是一个类型错误,或不?好吧,事实证明这个代码在.Net Core上失败,但在Mono上运行。
注意:我目前没有可供我测试的Windows机器,所以我不知道它在.Net Framework上的表现如何(假设版本为4.7.1,因为我在Mono 5.10上运行)哪个supports .Net 4.7.1根据他们的发行说明。但我编译了net461
目标,所以也许.Net Framework 4.6.1将是一个更好的选择来测试)。
所以我的问题是,哪种行为是正确的?复制零长度数组会在Mono上引发类型错误,这是我应该在Mono上报告的错误吗?或者.Net Core的实现是错误的,并且源数组长度为0的事实应该是“赢了”,并且不应该抛出类型错误?在我见过的任何.Net / C#/ F#文档中,我都没有遇到过这种特殊情况的引用,所以我不知道.Net CLR规范在这种情况下会发生什么。