Подтвердить что ты не робот

Как string.Format обрабатывает нулевые значения?

В следующем ниже коде, почему два вызова string.Format не ведут себя одинаково? В первом случае исключение не выбрасывается, а во втором бросается 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);
}

Может кто-нибудь, пожалуйста, помогите мне понять разницу между этими двумя?

4b9b3361

Ответ 1

Я угадываю здесь, но, похоже, разница в том, что перегруженный вызов вы нажимаете. String.Format имеет несколько перегрузок, это то, о чем вы нажимаете.

В первом примере было бы разумно, что вы нажимаете String.Format(string,object).

Во втором примере, предоставляя null, вы, скорее всего, нажмете String.Format(string,params object[]), который в документации приведет к повышению ArgumentNullException, когда:

Формат

или 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();

Ответ 2

В первом примере вы нажмете Format(String, Object), который выглядит при этом разобранным:

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

Обратите внимание на new object[] вокруг этого.

Во-вторых, вы, по-видимому, нажимаете на использование 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");
    }
...
}

... welp, вот ваша проблема, прямо сейчас! Первый вызов заключается в его переносе в новый массив, поэтому он не равен нулю. Передача в null явно не делает этого, из-за конкретного экземпляра Format(), вызывающего.

Ответ 3

Первый вызов разрешается как вызов Format (object), а второй определяется как вызов Format (object []). Параметр Null обрабатывается по-разному этими различными перегрузками.

Описание перегрузки описано здесь. Соответствующая часть состоит в том, что для второго вызова Format, перегрузка формата (params object []) расширяется до Format (object []), который предпочтительнее Format (object). Литеральное значение null - это как объект [], так и объект, но объект [] более конкретный, поэтому он выбран.

Ответ 4

Если вы используете интерполированную строку ($ "", другой способ форматирования), нулевое значение игнорируется, пропускается. Так

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

выдаст: "Это строка в строке". Конечно, вы можете использовать оператор объединения нулей в случае нуля для получения необходимого результата:

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

Ответ 5

Существуют два отличия:

  • Здесь назначается значение Null.

    Exception e = null;
    string msgOne = string.Format("An exception occurred: {0}", e);
    
  • Здесь значение Null не может быть прочитано в строковом формате, что означает ошибку при выдаче типа.

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

Я приведу вам простой пример: Здесь вы не можете прочитать значение NULL в виде строкового формата.

string str = null.toString();