C# 字符串长度计算不正确
我的同事和我正在调试他正在处理的WCF服务中的一个问题,其中字符串的长度计算不正确。他正在运行此方法以对其WCF服务中的方法进行单元测试:C# 字符串长度计算不正确,c#,wcf,string,C#,Wcf,String,我的同事和我正在调试他正在处理的WCF服务中的一个问题,其中字符串的长度计算不正确。他正在运行此方法以对其WCF服务中的方法进行单元测试: // Unit test method public void RemoveAppGroupTest() { string addGroup = "TestGroup"; string status = string.Empty; string message = string.Empty; appActiveDirecto
// Unit test method
public void RemoveAppGroupTest()
{
string addGroup = "TestGroup";
string status = string.Empty;
string message = string.Empty;
appActiveDirectoryServicesClient.RemoveAppGroup("AOD", addGroup, ref status, ref message);
}
// Inside the WCF service
[OperationBehavior(Impersonation = ImpersonationOption.Required)]
public void RemoveAppGroup(string AppName, string GroupName, ref string Status, ref string Message)
{
string accessOnDemandDomain = "MyDomain";
RemoveAppGroupFromDomain(AppName, accessOnDemandDomain, GroupName, ref Status, ref Message);
}
public AppActiveDirectoryDomain(string AppName, string DomainName)
{
if (string.IsNullOrEmpty(AppName))
{
throw new ArgumentNullException("AppName", "You must specify an application name");
}
}
我们试图进入.NET源代码以查看string.IsNullOrEmpty接收到的值,但当我们尝试计算变量时,IDE打印了此消息:“无法获取局部值或参数‘value’,因为它在此指令指针处不可用,可能是因为它已被优化。”(所有涉及的项目都没有启用优化)。因此,我们决定在长度检查之前,在方法本身内部显式设置变量的值,但这没有帮助
// Lets try this again.
public AppActiveDirectoryDomain(string AppName, string DomainName)
{
// Explicitly set the value for testing purposes.
AppName = "AOD";
if (AppName == null)
{
throw new ArgumentNullException("AppName", "You must specify an application name");
}
if (AppName.Length == 0)
{
// This exception gets thrown, even though it obviously isn't a zero length string.
throw new ArgumentNullException("AppName", "You must specify an application name");
}
}
我们在这件事上真的很紧张。还有其他人经历过这样的行为吗?关于调试它有什么建议吗
下面是发生行为的
AppActiveDirectoryDomain
对象的MSIL:
.method public hidebysig specialname rtspecialname instance void .ctor(string AppName, string DomainName) cil managed
{
.maxstack 5
.locals init (
[0] class [System]System.Net.NetworkCredential ldapCredentials,
[1] string[] creds,
[2] string userName,
[3] class [mscorlib]System.ArgumentNullException exc,
[4] class [System.DirectoryServices]System.DirectoryServices.ActiveDirectory.DirectoryContext directoryContext,
[5] class [System.DirectoryServices]System.DirectoryServices.ActiveDirectory.Domain domain,
[6] class [System.DirectoryServices.Protocols]System.DirectoryServices.Protocols.LdapException V_6,
[7] class [mscorlib]System.Exception V_7,
[8] bool CS$4$0000,
[9] char[] CS$0$0001,
[10] string[] CS$0$0002)
L_0000: ldarg.0
L_0001: ldsfld string [mscorlib]System.String::Empty
L_0006: stfld string MyNamespace.MyClass.AppActiveDirectoryDomain::appOU
L_000b: ldarg.0
L_000c: call instance void [mscorlib]System.Object::.ctor()
L_0011: nop
L_0012: nop
L_0013: ldstr "AOD"
L_0018: call bool [mscorlib]System.String::IsNullOrEmpty(string)
L_001d: ldc.i4.0
L_001e: ceq
L_0020: stloc.s CS$4$0000
L_0022: ldloc.s CS$4$0000
L_0024: brtrue.s L_0037
L_0026: nop
L_0027: ldstr "AppName"
L_002c: ldstr "You must specify an application name"
L_0031: newobj instance void [mscorlib]System.ArgumentNullException::.ctor(string, string)
L_0036: throw
以及字符串.IsNullOrEmpty
调用的MSIL:
.method public hidebysig static bool IsNullOrEmpty(string 'value') cil managed
{
.maxstack 8
L_0000: ldarg.0
L_0001: brfalse.s L_000d
L_0003: ldarg.0
L_0004: callvirt instance int32 System.String::get_Length()
L_0009: ldc.i4.0
L_000a: ceq
L_000c: ret
L_000d: ldc.i4.1
L_000e: ret
}
编辑: 以下是引发ArgumentNullException时“Watch”窗口中变量的屏幕截图: 另外,第二个屏幕截图显示了检查字符串长度时抛出的异常,在上面5行显式声明该字符串后: 更新#3:我们尝试更改局部变量的名称,它通过了null检查和长度检查,但在调用
string.IsNullOrEmpty
时失败。请参见此屏幕截图:
响应:
- 我们不使用任何工具来修改MSIL。我们已经执行了清理,还手动删除了构建目录中的所有文件,并强制重新生成…同样的结果
- 以下语句的计算结果为true并进入if块:
if(string.IsNullOrEmpty(“AOD”){/**}
- 构造函数的调用方式如下:
试试看 { 使用(AppActiveDirectoryDomain=new AppActiveDirectoryDomain(AppName,DomainName)) { } }
我有两个建议
我知道第2点可能看起来毫无意义,但我在过去遇到过似乎无法解释的情况,结果发现没有编译某些内容或存在范围冲突,而调试器显示了您所期望的内容。而且,尝试一下也无妨:)这是一个64位问题。或者至少这只是一个运行64位的问题。在64位操作系统上的IIS 7.0中,默认情况下,所有网站都托管在64位进程中。如果我们将服务设置为托管在32位进程中,问题就会消失。如果在抛出的异常上放置断点,并将
AppName
和AppName.Length
添加到手表中,它们会显示什么?它们会显示“AppName=”AOD“和“AppName.Length==3”-因此它们的计算结果正确。我在问题的底部附上了一个屏幕截图。你可以让测试更加清晰:如果(“AOD”.Length==0)抛出…
。这将排除变量AppName
作为问题的来源。如果仍然抛出异常,您可能对此无能为力。另一个问题:在单元测试方法和抛出的异常之间,调用了AppActiveDirectoryDomain
的构造函数在哪里?你也能展示一下代码吗?5/3:今天我们将尝试在不同的工作站上运行测试。如果我们收到同样的错误,我可能会开始悬赏。否则,我们将假定他安装的VS2008/.NET已损坏。我们尝试为局部变量使用不同的名称,它成功地进行了手动空值检查和长度检查,但在string.IsNullOrEmpty
中失败。查看我发布的第三个截图链接。我发布了IL。我们两人都不觉得可疑,但我们都不是IL专家。@Justin,IL看起来不错。。。您能否将一些消息写入调试窗口(Diagnostics.debug.WriteLine)。我们可以看到调试器看到了什么,但这可能有助于查看执行代码看到了什么。