我有一个.Net 4.6项目引用了一个3.5程序集。这个程序集在其中一个接口中定义了以下方法,我可以使用Resharper反编译器进行检查。
void WriteString([MarshalAs(UnmanagedType.BStr), In] string data, [In] bool flushAndEND = true);
请注意最后一个可选参数
flushAndEND
,它的默认值为true
。现在的问题是,当我在我的项目中使用这个方法时,将鼠标悬停在方法名称上会显示通常的VS工具提示,其中详细介绍了方法签名,但对于我来说,它显示了可选参数flushAndEND
的错误默认值。以下是屏幕截图。
为了让事情变得更糟,我注意到在运行时,当只调用带有第一个参数的方法WriteString
时,flushAndEND
被设为false
而非其在我正在引用的DLL中定义的默认值。这对我们项目的影响很大,因为它使我们应用程序的一个重要功能无法使用,并阻止了我们的一大部分回归测试。当我调用该方法时,我可以通过强制将可选参数的值设置为true来解决这个问题,但是我担心项目中其他地方也存在同样的问题。因此,我需要一个更好的解决方案或者至少了解这种行为背后的原因。
我们几周前刚刚升级了环境。之前我们使用的是VS2013,一切都工作正常。
我知道已确认的 .Net 4.6 错误会导致某些参数传递错误的值,我可以将其与我的问题联系起来,但是正如文章中所说,该错误仅在编译为x64架构时发生。我的项目是一个WPF应用程序,我们将其编译为x32。
为什么使用错误的默认参数调用
WriteString
?我稍后会尝试在一个小项目中分离问题,并查看是否能够重现该问题。
编辑:我已经成功地分离出了问题,并发现了一些有趣的东西!
我创建了一个简单的.NET 4.6控制台应用程序,添加了对我的DLL的引用,并编写了以下简单代码,其中包括向设备发送命令并读取响应:
private static void Main(string[] args)
{
//Init managers
ResourceManager ioMgr = new ResourceManagerClass();
FormattedIO488 instrument = new FormattedIO488Class();
//Connect to the USB device
instrument.IO = (IMessage)ioMgr.Open("USB0::0x0957::0x0909::MY46312358::0::INSTR");
string cmd = "*IDN?";
//This is the problematic method from my dll
instrument.WriteString(cmd);
//Read the response
string responseString = instrument.ReadString();
Console.WriteLine(responseString);
Console.ReadKey();
}
我接下来做的是从VS 2013和VS 2015两个版本中打开此项目。在两个版本的VS中,我都重新构建了该项目并运行它。以下是结果:
VS2013:使用正确的默认值
flushAndEND
(即true
,意味着刷新缓冲区并结束命令)调用了WriteString
。VS2015:使用错误的默认值
flushAndEND
调用了WriteString
,导致超时异常。进一步检查发现,VS2013中的对象浏览器查看器显示方法签名为:
void WriteString(string data, [bool flushAndEND = True])
在VS2015中,对象浏览器显示的方法签名为:
void WriteString(string data, [bool flushAndEND = False])
唯一的解释是,VS2015编译器从程序集中读取的默认值不正确。