9

我只是想调试以下异常:

Exception has been thrown by the target of an invocation.: System.Reflection.TargetInvocationException: 
Exception has been thrown by the target of an invocation. ---> 
System.ArgumentOutOfRangeException: Specified argument was out of the range of valid values.
Parameter name: newAddress
   at System.Net.IPAddress..ctor(Int64 newAddress)

这是有问题的代码:

int hostToNetworkOrder = IPAddress.HostToNetworkOrder( (int)computer.IpAddress );
IPAddress ipAddress = new IPAddress( hostToNetworkOrder );

computer.IpAddress设置为1582281193。这将转换为hostToNetworkOrder,即-374255778

现在,如果我尝试new IPAddress( -374255778 );在 Visual Studio 的即时窗口中构建,我会得到一个包含正确 IP 地址的 IPAddress 对象。

但是如果我越过代码中的那一行,它总是会抛出一个 ArgumentOutOfRangeException。为什么?


更新

我知道我的意见是负面的,很可能是这个问题的根源。这就是我解决它的方法:

UInt32 hostToNetworkOrder = (UInt32)IPAddress.HostToNetworkOrder( (Int32)computer.IpAddress );
IPAddress ipAddress = new IPAddress( hostToNetworkOrder );

我仍然不明白为什么它在立即窗口中起作用。

4

4 回答 4

8

查看 ILSpy 中的 IPAddress 类,有一个内部构造函数采用 int 并且不执行参数超出范围检查 - 我感觉它可能在监视窗口中调用该构造函数,但在实际代码中它调用public ctor(long),它确实验证了这个数字。

为了测试我的理论,我只是尝试了这段代码:

var ipAddress = (IPAddress) typeof (IPAddress)
                                        .GetConstructor(
                                            BindingFlags.NonPublic | BindingFlags.Instance,
                                            null,
                                            new[] {typeof (int)},
                                            null)
                                        .Invoke(new object[] {hostToNetworkOrder });

而且,果然,IPAddress 类的构造没有错误。

于 2012-04-10T12:03:14.970 回答
3

我仍然不明白为什么它在立即窗口中起作用。

这是你问题的症结所在。您不指望的是用于在即时窗口中解析您的表达式的调试器表达式评估器的有些奇怪的行为。最好使用具有类似于 IPAddress 的代码的示例解决方案来演示这一点。创建一个控制台模式项目并添加一个类库项目。使类库源代码文件如下所示:

using System;

namespace Foo {
    public class Test {
        public string how;
        internal Test(int arg) { how = "internal"; }
        public Test(long arg) { how = "public"; }
        public string ToString() { return how; }
    }
}

控制台应用程序的 Program.cs 文件如下所示:

using System;
using Foo;

class Program {
    static void Main(string[] args) {
        new Test(999);
    }   // <== set breakpoint here
}

当断点命中时,按 F5 并切换到“立即”窗口。类型:

new Foo.Test(-1).ToString()

你会看到:

"internal"

它选择了内部构造函数而不是公共构造函数

与 IPAddress 发生的事情相同,它有一个内部构造函数,该构造函数接受一个不检查参数的 int。虽然这听起来像一个错误,但提供对私有和内部成员的访问是正常的调试器行为。通常,请始终牢记调试器表达式求值器不是由 C# 编译器驱动的。它没有使用与语言完全相同的规则,也没有像语言那样具有完全的表现力。希望 Roslyn 项目完成后的某一天会有所改善。

于 2012-04-10T12:39:20.263 回答
1

System.ArgumentOutOfRangeException当 ip 地址低于零或高于 0x00000000FFFFFFFF 时,您会得到一个,如此处所示

IPAddress 构造函数接受一个 long 类型的参数(一个 64 位整数),但是您传递给它的是一个 32 位整数,该整数将被转换为一个 long。

于 2012-04-10T11:47:12.113 回答
0

我遇到了同样的问题,我正在将 IP 转换为 int32:

    Int32 IP1 = Convert.ToInt32(arrIP[0]);
    Int32 IP2 = Convert.ToInt32(arrIP[1]);
    Int32 IP3 = Convert.ToInt32(arrIP[2]);
    Int32 IP4 = Convert.ToInt32(arrIP[3]);
    long ipInt = IP1 + (IP2 * 256) + (IP3 * 256 * 256) + (IP4 * 256 * 256 * 256);
    IPAddress ipadr = new IPAddress(ipInt);
    IPEndPoint ipe = new IPEndPoint(ipadr, port);

对于某些 IP,它正在转换为负数。我所做的唯一更改是使用 int64,它解决了我的问题。

        Int64 IP1 = Convert.ToInt64(arrIP[0]);
        Int64 IP2 = Convert.ToInt64(arrIP[1]);
        Int64 IP3 = Convert.ToInt64(arrIP[2]);
        Int64 IP4 = Convert.ToInt64(arrIP[3]);
于 2015-04-21T06:37:56.697 回答