如何设置一个c#方法范围的变量影响另一个?

时间:2011-03-31 15:35:50

标签: c# service clr debugging

这个真让我难过。我和另一位打电话给我的开发商合作,因为他无法相信他所看到的。我们一起调试了调试器,我也看到了它并没有解释。这是场景。他正在编写一个通过自动生成的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输出构建文件夹中。

这有什么合理的解释吗?我很难过如何继续。

4 个答案:

答案 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));