这个真让我难过。我和另一位打电话给我的开发商合作,因为他无法相信他所看到的。我们一起调试了调试器,我也看到了它并没有解释。这是场景。他正在编写一个通过自动生成的COM包装器与第三方COM对象进行交互的方法(仅通过添加COM组件作为参考生成。这是他的方法的顶部:
public bool RefolderDocument(ref IManDocument oDoc)
{
string strCustom1 = (string) oDoc.GetAttributeValueByID(imProfileAttributeID.imProfileCustom1);
string strCustom2 = (string) oDoc.GetAttributeValueByID(imProfileAttributeID.imProfileCustom2);
代码的目的是从“文档”对象(oDoc)获取项目编号和子项目编号。
以下是您逐步完成后会发生的事情。在第一次赋值之后,strCustom1具有期望值“32344”(项目编号),并且strCustom2按预期为空。在第二次分配之后,strCustom2获取子项目编号“0002” - 但strCustom1已更改为32334 - 一个字符已更改!?
它让我感到震惊,因为某种老式的c语言堆栈溢出(即使它与COM组件互操作,我也不希望在托管应用程序中使用它)。我们都感到困惑。为了解决这个奇怪的问题,我尝试将第一个字符串的内容复制到另一个位置,如下所示:
public bool RefolderDocument(ref IManDocument oDoc)
{
string strCustom1 = string.Copy((string)oDoc.GetAttributeValueByID(imProfileAttributeID.imProfileCustom1));
string strCustom2 = string.Copy((string)oDoc.GetAttributeValueByID(imProfileAttributeID.imProfileCustom2));
结果相同!我们此时正在抓住吸管,并将代码从.NET 4中删除到.NET 3.5(CLR 2),但没有变化。一个可能相关的观点是,这是一项服务,我们将附加到服务流程。构建目标是x86,服务位置肯定在Debug输出构建文件夹中。
这有什么合理的解释吗?我很难过如何继续。
答案 0 :(得分:1)
看起来strCustom1和strCustom2都被设置为引用,返回GetAttributeValueByID的结果。我不知道为什么,看看这里是否还有其他人(Paging Dr. Skeet lol ......)会很有趣。
在短期内,我认为你会发现这会为你解决问题......
public bool RefolderDocument(ref IManDocument oDoc)
{
string strCustom1 = "" + string.Copy((string)oDoc.GetAttributeValueByID(imProfileAttributeID.imProfileCustom1));
string strCustom2 = "" + string.Copy((string)oDoc.GetAttributeValueByID(imProfileAttributeID.imProfileCustom2));
我的想法基本上是让它评估表达而不是直接使用引用...
马丁。
聚苯乙烯。 string.Copy()有什么用?
答案 1 :(得分:1)
COM对象可能没有遵循COM内存管理规则,它覆盖了CLR认为拥有的内存。像GetEnumerator()没有创建新对象这样的简单事情可以真正搞砸COM互操作和它的缓存。
您还必须意识到,COM调用实际工作的方式是通过向字符串的内存传递引用。虽然你称之为:
str = oDoc.GetAttributeValueByID(imProfileAttributeID.imProfileCustom1)
这真的叫做:
hresult = oDoc.GetAttributeValueByID(imProfileAttributeID.imProfileCustom1,&str)
所以你可以看到COM对象有一个指针直接进入CLR内存。
换句话说,查看COM对象,而不是.NET代码。
答案 2 :(得分:1)
我遇到过类似于你所描述的问题。
我的情况是,.NET /编译器/ runtine / CLR工作得很好,唯一的问题是visual studio调试器显示的值不正确。尝试写下您的值,例如到System.Diagnostics.Trace或控制台,检查这是否是你的情况。
答案 3 :(得分:0)
我不确切知道为什么或如何发生这种情况,我希望有人能得到答案。作为解决方法,我会将返回的字符串解析为int,然后执行第二个语句。至少那会解决丢失的价值问题。
int Custom1 = int.Parse((string)oDoc.GetAttributeValueByID(imProfileAttributeID.imProfileCustom1));
int Custom2 = int.Parse((string)oDoc.GetAttributeValueByID(imProfileAttributeID.imProfileCustom2));