防止编译器将两个动态对象优化成一个

3

我在VS2012中有一个大型MVC4应用程序,其中控制器函数返回简单的动态对象(作为JSON)到jQuery $.post函数。

看起来编译器将具有相同属性定义(但不同大小写)的对象合并为同一对象。这会导致在尝试在JavaScript中读回属性时出现问题。

Dim js As New System.Web.Script.Serialization.JavaScriptSerializer()

'should return  {"TEST":true} and does
MessageBox.Show(js.Serialize(New With {.TEST = True})) 

' should return  {"test":true} but returns {"TEST":true} if the above code exists.
MessageBox.Show(js.Serialize(New With {.test = True})) 

由于项目庞大,开发人员众多,因此不总是实际可行的扫描代码以查找此问题的实例。

有没有办法防止这种优化?


又一个不使用VB的理由。;-) - T.J. Crowder
可能只是名称被缓存了。https://dev59.com/D2nWa4cB1Zd3GeqP38fR - the_lotus
嗨@the_lotus,感谢您的建议。在我的情况下,JSON序列化甚至在结果传递到控制器函数之前就出错了,因此缓存不可能是原因。 - Arvi Sehmi
你尝试过将属性更改为test123进行尝试吗?由于两个Serialize调用使用相似的对象,VB可能会优化并使用相同的实例。翻转这两个调用将产生2个小写字母。我还没有查看编译后的代码以进行验证。 - the_lotus
我应该说“可能会优化并使用相同的定义”,而不是“可能会优化并使用相同的实例”。是否可以创建实际的类呢? - the_lotus
再次感谢@the_lotus的建议。如果我更改属性名称,一切都会按预期工作,问题在于此类型的返回模式在项目中许多控制器函数中都在使用。这是一个大型项目(数百个MVC控制器),因此如果两个开发人员恰好使用类似的返回对象,则JavaScript将立即出现问题,因为一个开发人员使用不同大小写的属性名称。我们可以开始使用具体的类定义,但可能会为每个控制器函数创建额外的类,这对于项目的规模来说将是一个缺点。 - Arvi Sehmi
1个回答

1
VB.Net不区分大小写,因此会将大小写不同的动态类型视为相同的类型。这是语言本身的特性,无法更改。类/参数等只有大小写不同的情况也被视为相同/不允许。这不是“编译器优化”的结果,而是语言本身的工作方式。
由于编译器创建动态类型的方式,必须将相同签名的类型合并为一个类型(否则您将永远无法再次创建相同的类型)。加上VB的特性,这意味着您被限制了。
所以你确实有几个选择:
  1. 在整个组织中强制执行一致的编码规范。可以通过提交政策、代码审查或其他适合您的流程来实施。
  2. 使用现有的静态分析和编译器源代码,您可能可以构建一个静态代码分析规则来检测此情况。但这并不容易。
  3. 为返回类型使用命名类,从而避免出现问题。我知道你害怕类膨胀,但如果您在多个控制器中使用相同的动态类型,那么您可能应该使用静态类。而且,一个文件的成本是什么?没有什么成本。这是最佳选择,也是最可维护的选择。

谢谢Tim。我们最终选择了第三个选项;为了纯粹返回JSON,我们在每个区域的控制器下创建了一个单独的命名空间来存放对象。 - Arvi Sehmi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接