C#不会在开头附近编译一个长度为\ 0的常量string

我遇到了一个特殊情况,在创build特定types的string时出现以下错误:

意外的错误编写debugging信息 – '错误HRESULT E_FAIL已经从调用COM组件返回。

这个错误对于Stack Overflow来说并不新鲜(请看这个问题和这个问题 ),但是这个问题与这个问题没有任何关系。

对于我来说,当我创build一个特定长度的conststring时,会发生这种情况,这个string在开始的某个地方包含一个空字符( \0 )。

重现,首先生成一个适当长度的string,例如使用:

 var s = new string('a', 3000); 

在运行时抓取结果string(例如立即窗口或hover在variables上并复制其值)。 然后,做一个const

 const string history = "aaaaaa...aaaaa"; 

最后,把\0放在某处:

 const string history = "aaaaaaaaaaaa\0aa...aaaaa"; 

我注意到的一些事情:

  • 如果你把\0放在最后,错误不会发生。
  • 转载使用.NET Framework 4.6.1和4.5
  • 如果string很短,则不会发生。
  • 编辑 :更多宝贵的信息可在下面的评论。

任何想法为什么发生这种情况? 这是一种错误吗?

编辑 : 错误提交,包括来自评论的信息。 谢谢大家。

我会稍微谈谈这个问题。 在VS2015和更早版本中都会出现此问题。 因此,与C#编译器本身没有直接关系,这在ISymUnmanagedWriter2 :: DefineConstant2()实现方法中是错误的。 ISymUnmanagedWriter2是一个COM接口,是所有编译器使用的.NET基础结构的一部分。 并用于Roslyn和传统的C#编译器。

在使用该方法的Roslyn源代码(实际上可以追溯到CCI项目 )中的注释足够充分,以前发现的这种方法存在麻烦:

 // EDMAURER If defining a string constant and it is too long (length limit is undocumented), this method throws // an ArgumentException. // (see EMITTER::EmitDebugLocalConst) try { this.symWriter.DefineConstant2(name, value, constantSignatureToken); } catch (ArgumentException) { // writing the constant value into the PDB failed because the string value was most probably too long. // We will report a warning for this issue and continue writing the PDB. // The effect on the debug experience is that the symbol for the constant will not be shown in the local // window of the debugger. Nor will the user be able to bind to it in expressions in the EE. //The triage team has deemed this new warning undesirable. The effects are not significant. The warning //is showing up in the DevDiv build more often than expected. We never warned on it before and nobody cared. //The proposed warning is not actionable with no source location. } catch (Exception ex) { throw new PdbWritingException(ex); } 

吞咽exception,tsk,tsk。 它死在你的情况的最后一个catch语句。 他们深入挖掘了一些反向工程来解决string长度问题:

 internal const int PdbLengthLimit = 2046; // Empirical, based on when ISymUnmanagedWriter2 methods start throwing. 

这是相当接近的\ 0开始投掷,我得到了2034年。没有什么,你或任何其他人可以做这个当然。 你可以合理地做的是报告在connect.microsoft.com的错误。 但是,希望你看到墙上的文字,它将被固定的可能性是相当小的。 这是没有人维护的代码,它现在有'无证'的地位,从其他评论来看,这远远早于.NET。 不是Ed Maurer 🙂

解决方法应该很简单,在运行时将这个string粘在一起。

我能够重新编码的问题。 然后我把声明改为:

const string history = @“aaa \ 0aaa …很多很多的aaa … aaa”;

再次尝试,它编译得很好。