设置一个c#方法作用域变量如何影响另一个?

设置一个c#方法作用域变量如何影响另一个?,c#,service,clr,debugging,C#,Service,Clr,Debugging,这件事真让我难堪。我正在与另一位开发人员合作,他打电话给我,因为他无法相信他所看到的。我们一起通过了调试器,我也看到了,没有解释。下面是一个场景。他正在编写一个方法,该方法通过自动生成的COM包装器与第三方COM对象交互(只需添加COM组件作为引用即可生成)。下面是他的方法的顶部: public bool RefolderDocument(ref IManDocument oDoc) { string strCustom1 = (string) oDoc.GetAtt

这件事真让我难堪。我正在与另一位开发人员合作,他打电话给我,因为他无法相信他所看到的。我们一起通过了调试器,我也看到了,没有解释。下面是一个场景。他正在编写一个方法,该方法通过自动生成的COM包装器与第三方COM对象交互(只需添加COM组件作为引用即可生成)。下面是他的方法的顶部:

  public bool RefolderDocument(ref IManDocument oDoc)
    {
        string strCustom1 = (string) oDoc.GetAttributeValueByID(imProfileAttributeID.imProfileCustom1);
        string strCustom2 = (string) oDoc.GetAttributeValueByID(imProfileAttributeID.imProfileCustom2);
代码的目的是从“文档”对象(oDoc)获取项目编号和子项目编号

下面是您一步一步完成时发生的情况。在第一次赋值之后,strustom1的预期值为“32344”(项目编号),strustom2的预期值为空。在第二次赋值之后,strustom2的子项目编号为“0002”-,但strustom1已更改为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,服务位置肯定在调试输出构建文件夹中


有什么合乎逻辑的解释吗?我不知道如何继续。看起来strustom1和strustom2都被设置为GetAttributeValueByID结果的引用。我不知道为什么,看看这里的其他人(呼叫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));
我的想法基本上是让它计算表达式,而不是直接使用引用

马丁


Ps.string.Copy()是怎么回事?

COM对象可能没有遵循COM内存管理规则,而且它正在覆盖CLR认为它拥有的内存。不为GetEnumerator()创建新对象之类的简单操作实际上会破坏COM互操作和缓存

您还必须意识到,COM调用的实际工作方式是通过为字符串传递对内存的引用

str = oDoc.GetAttributeValueByID(imProfileAttributeID.imProfileCustom1)
它实际上更像是:

hresult = oDoc.GetAttributeValueByID(imProfileAttributeID.imProfileCustom1,&str)
因此,您可以看到COM对象有一个指向CLR内存的指针


换句话说,看看COM对象,而不是你的.NET代码。

我不知道发生这种情况的确切原因或原因,我希望有人能给出答案。作为一种解决方法,我会将返回的字符串解析为int,然后执行第二条语句。至少这样可以解决丢失值的问题

int Custom1 = int.Parse((string)oDoc.GetAttributeValueByID(imProfileAttributeID.imProfileCustom1));
int Custom2 = int.Parse((string)oDoc.GetAttributeValueByID(imProfileAttributeID.imProfileCustom2));

我遇到过与您描述的问题相似的问题


在我的案例中,.NET/compiler/runtine/CLR工作得很好,唯一的问题是visual studio调试器显示的值不正确。请尝试将您的值写入System.Diagnostics.Trace或控制台,以检查这是否是您的情况。

Tony,感谢您的回复。不幸的是,COM对象归供应商所有,应该是time te斯特德:-。有趣的是一个字符在另一个变量中间的变化!也许其中一个建议的解决办法会奏效。@Decker,是的,这是不幸的。我遇到了许多在.NET下失败的“经过时间测试”的COM DLL问题,因为它们没有遵守COM interop期望它们遵守的规则。我害怕内存损坏,如果我实现了复制的解决方案-如果你幸运的话,它只是一个调试器问题(我只在C++中看到,而不是.NET,但还有一些是报告.NET)。如果您使用.NET4.0并通过ole自动化,我建议您尝试使用动态类型,但需要首先了解更改数据的来源。是的。Copy是在源位置被覆盖之前,试图移动strustom1实际指向的位置。我希望这能奏效。没有,这很有趣。我认为情况并非如此,因为它看起来好像值确实发生了变化。事实上,我们之所以仔细检查这个代码部分,是因为一些审计代码检测到了差异。但把它扔出跟踪系统以确认它不是调试器显示问题并没有什么坏处。这也是我的猜测。将每个点的值写入日志,并以这种方式进行分析。我看不出复制的字符串是如何变化的。