Как 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);
}
Может кто-нибудь, пожалуйста, помогите мне понять разницу между этими двумя?
Ответы
Ответ 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();