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です。

ここで、Visual Studioのイミディエイトウィンドウで作成しようとするとnew IPAddress( -374255778 );、正しい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

私がまだ理解していないのは、それがイミディエイトウィンドウでまったく機能した理由です。

これがあなたの質問の核心です。期待していないのは、イミディエイトウィンドウで式を解析するために使用されるデバッガー式エバリュエーターのやや奇妙な動作です。これは、IPアドレスのように動作するコードを使用したサンプルソリューションで最もよく示されます。コンソールモードプロジェクトを作成し、クラスライブラリプロジェクトを追加します。クラスライブラリのソースコードファイルを次のようにします。

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アドレスが0未満または0x00000000FFFFFFFFを超えると、が表示されます

IPAddressコンストラクターはlong型(64ビット整数)のパラメーターを取りますが、longに変換される32ビット整数を渡します。

于 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 に答える