为什么IPAddress有时会抛出ArgumentOutOfRangeException?

时间:2012-04-10 11:32:50

标签: c#

我只是试图调试以下异常:

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

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

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


更新

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

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

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

4 个答案:

答案 0 :(得分:8)

查看ILSpy中的IPAddress类,有一个内部构造函数,它接受一个int并且不进行范围检查 - 我觉得它可能在监视窗口中调用该构造函数但在实际代码中它调用公共ctor(长),它确实验证了这个号码。

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

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

并且,当然,构造的IPAddress类没有错误。

答案 1 :(得分: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。虽然这会像bug一样大声嘎嘎叫,但提供对私有和内部成员的访问是正常的调试器行为。通常,请始终牢记调试器表达式计算器由C#编译器驱动。它没有使用与语言完全相同的规则,也没有完整的表达能力作为语言。希望Roslyn完成项目后的某一天会有所改善。

答案 2 :(得分:1)

当ip地址低于零或高于0x00000000FFFFFFFF时,您会看到System.ArgumentOutOfRangeException,如here所示。

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

答案 3 :(得分: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]);