70

以下のコードで、2つのstring.Format呼び出しが同じように動作しないのはなぜですか?最初の例では例外はスローされませんが、2番目の例では例外がスローさArgumentNullExceptionれます。

static void Main(string[] args)
{
    Exception e = null;
    string msgOne = string.Format("An exception occurred: {0}", e);
    string msgTwo = string.Format("Another exception occurred: {0}", null);
}

誰かが私が2つの違いを理解するのを手伝ってくれませんか?

4

5 に答える 5

56

私はここで推測していますが、それはあなたが打っている過負荷の呼び出しの違いのようです。 String.Format複数あります。

最初の例では、ヒットしているのは理にかなっていますString.Format(string,object)

2番目の例では、ドキュメントによると、次の場合に発生する可能性が最も高いものを提供しnullます。String.Format(string,params object[])ArgumentNullException

formatまたはargsがnullです。

.NET4を実行している場合は、名前付きパラメーターを使用してみてください。

String.Format("Another exception occured: {0}", arg0: null);

なぜparams object[]過負荷になっているのですか?おそらくはnullオブジェクトではなく、その方法は、呼び出しで各値を新しいオブジェクトとしてparams渡す、値の配列を渡すことができるためですつまり、以下は同じものです:

String.Format("Hello, {0}! Today is {1}.", "World", "Sunny");
String.Format("Hello, {0}! Today is {1}.", new Object[]{ "World", "Sunny" })

つまり、ステートメント呼び出しを次のように変換します。

String format = "Another exception occured: {0}";
Object[] args = null;
String.Format(format, args); // throw new ArgumentNullException();
于 2012-11-07T19:11:54.540 に答える
12

最初の例では、を押してFormat(String, Object)います。これは、分解すると次のようになります。

 public static string Format(string format, object arg0)
 {
    return Format(null, format, new object[] { arg0 });
 }

new object[]その周りに注意してください。

2つ目は、明らかにFormat(string, object[])使用法に達していることです。少なくとも、同じテストを実行したときに呼び出されるものです。分解すると、次のようになります。

 public static string Format(string format, params object[] args)
 {
     return Format(null, format, args);
 }

したがって、これらはすべて実際にに集中しFormat(IFormatProvider, string, object[])ます。かっこいい、最初の数行を見てみましょう。

public static string Format(IFormatProvider provider, string format, params object[] args)
{
    if ((format == null) || (args == null))
    {
        throw new ArgumentNullException((format == null) ? "format" : "args");
    }
...
}

...ウェルプ、あなたの問題があります、すぐそこに!最初の呼び出しはそれを新しい配列でラップしているので、nullではありません。Format()nullを明示的に渡しても、その呼び出しの特定のインスタンスのため、それは行われません。

于 2012-11-07T19:12:10.380 に答える
6

補間された文字列($ ""、フォーマットの別の方法)を使用する場合、nullは無視され、スキップされます。それで

string nullString = null;
Console.WriteLine($"This is a '{nullString}' in a string");

「これは文字列内の''です」を生成します。もちろん、nullの場合はnull合体演算子を使用して必要な出力を生成できます。

string nullString = null;
Console.WriteLine($"This is a '{nullString ?? "nothing"}' in a string");
于 2019-03-22T07:13:34.663 に答える
2

最初の呼び出しはFormat(object)の呼び出しとして解決され、2番目の呼び出しはFormat(object [])の呼び出しとして解決されます。ヌルパラメータは、これらの異なるオーバーロードによって異なる方法で処理されます。

過負荷の解決については、ここで説明します。関連する部分は、Formatの2回目の呼び出しで、Format(params object [])のオーバーロードがFormat(object [])に展開されることです。これは、Format(object)よりも優先されます。リテラルnullはobject[]とobjectの両方ですが、object []はより具体的であるため、それが選択されます。

于 2012-11-07T19:14:37.153 に答える
-3

次の2つの違いがあります。

  1. ここでは、Null値が割り当てられています。

    Exception e = null;
    string msgOne = string.Format("An exception occurred: {0}", e);
    
  2. ここで、Null値を文字列形式で読み取ることはできません。これは、型キャストエラーを意味します。

    string msgTwo = string.Format("Another exception occurred: {0}", null);
    

簡単な例を示します。ここでは、NULL値を文字列形式として読み取ることはできません。

string str = null.toString();
于 2012-11-08T18:40:54.563 に答える