Как сделать ToString для возможно нулевого объекта?

Есть ли простой способ сделать следующее:

String s = myObj == null ? "" : myObj.ToString();

Я знаю, что могу сделать следующее, но я действительно считаю это взломом:

String s = "" + myObj;

Было бы здорово, если Convert.ToString() имел правильную перегрузку для этого.

Ответ 1

С# 6.0 Редактировать:

С С# 6.0 теперь у нас может быть краткая версия оригинального метода без приведения:

string s = myObj?.ToString() ?? "";

Или даже используя интерполяцию:

string s = $"{myObj}";

Оригинальный ответ:

String s = (myObj ?? String.Empty).ToString();

или же

String s = (myObjc ?? "").ToString()

быть еще более кратким.

К сожалению, как уже указывалось, вам часто понадобится приведение с любой стороны, чтобы это работало с типами не String или Object:

String s = (myObjc ?? (Object)"").ToString()
String s = ((Object)myObjc ?? "").ToString()

Поэтому, хотя это может показаться изящным, актерский состав почти всегда необходим и не является таким кратким на практике.

Как предлагается в другом месте, я рекомендую, возможно, использовать метод расширения, чтобы сделать это чище:

public static string ToStringNullSafe(this object value)
{
    return (value ?? string.Empty).ToString();
}

Ответ 2

string.Format("{0}", myObj);

string.Format будет форматировать нуль как пустую строку и вызывать ToString() для непустых объектов. Насколько я понимаю, это то, что вы искали.

Ответ 3

Было бы здорово, если Convert.ToString() имел правильную перегрузку для этого.

Был Convert.ToString(Object value) с .Net 2.0 (примерно за 5 лет до того, как этот Q был задан), который, как представляется, делает именно то, что вы хотите:

http://msdn.microsoft.com/en-us/library/astxcyeh(v=vs.80).aspx

Я пропустил/неправильно интерпретировал что-то действительно очевидное здесь?

Ответ 4

С помощью метода расширения вы можете выполнить следующее:

public static class Extension
{
    public static string ToStringOrEmpty(this Object value)
    {
        return value == null ? "" : value.ToString();
    }
}

Следующие ничего не будут писать на экран и не будут вызывать исключение:

        string value = null;

        Console.WriteLine(value.ToStringOrEmpty());

Ответ 5

Я не согласен с этим:

String s = myObj == null ? "" : myObj.ToString();

- это хак. Я думаю, что это хороший пример четкого кода. Это абсолютно очевидно, чего вы хотите достичь, и что вы ожидаете нулевого.

ОБНОВЛЕНИЕ:

Теперь я вижу, что вы не говорили, что это был взлом. Но это подразумевало в том, что вы думаете, что это не путь. На мой взгляд, это, безусловно, самое ясное решение.

Ответ 6

string s = String.Concat(myObj);

был бы самым коротким, как я предполагаю, и также имел неэффективные служебные накладные расходы. Имейте в виду, хотя читателю кода было бы не совсем понятно, что это за намерение.

Ответ 7

На самом деле я не понял, что вы хотите сделать. Насколько я понимаю, вы можете написать этот код другим способом. Вы спрашиваете об этом или нет? Можете ли вы объяснить больше?

string s = string.Empty;
    if(!string.IsNullOrEmpty(myObj))
    {
    s = myObj.ToString();
    }

Ответ 8

Меня может отбить из-за моего ответа, но здесь все равно:

Я просто напишу

string s = "" if (myObj!= null) {  x = myObj.toString(); }

Есть ли выигрыш с точки зрения производительности для использования тернарного оператора? Я не знаю, с головы до ног.

И, очевидно, как кто-то, упомянутый выше, вы можете поместить это поведение в метод, такой как safeString (myObj), который позволяет повторно использовать.

Ответ 9

Комментарий Holstebroe будет вашим лучшим ответом:

string s = string.Format("{0}", myObj);

Если myObj равно null, формат помещает там пустое строковое значение.

Он также удовлетворяет вашим требованиям к одной строке и легко читается.

Ответ 10

У меня была такая же проблема, и я решил ее просто перебрасывать объект в строку. Это работает и для нулевых объектов, потому что строки могут быть нулями. Если вы абсолютно не хотите иметь пустую строку, это должно работать нормально:

string myStr = (string)myObj; // string in a object disguise or a null

Ответ 11

Некоторые (скоростные) тесты производительности, суммирующие различные параметры, а не то, что это действительно имеет значение #microoptimization (с помощью расширение linqpad)

Функции

void Main()
{
    object objValue = null;
    test(objValue);
    string strValue = null;
    test(strValue);
}

// Define other methods and classes here
void test(string value) {
    new Perf<string> {
        { "coallesce", n => (value ?? string.Empty).ToString() },
        { "nullcheck", n => value == null ? string.Empty : value.ToString() },
        { "str.Format", n => string.Format("{0}", value) },
        { "str.Concat", n => string.Concat(value) },
        { "string +", n => "" + value },
        { "Convert", n => Convert.ToString(value) },
    }.Vs();
}

void test(object value) {
    new Perf<string> {
        { "coallesce", n => (value ?? string.Empty).ToString() },
        { "nullcheck", n => value == null ? string.Empty : value.ToString() },
        { "str.Format", n => string.Format("{0}", value) },
        { "str.Concat", n => string.Concat(value) },
        { "string +", n => "" + value },
        { "Convert", n => Convert.ToString(value) },
    }.Vs();
}

Возможно, важно отметить, что Convert.ToString(...) сохранит нулевую строку.

Результаты

Объект

  • nullcheck 1.00x 1221 тиков (0.1221 мс) [в 10K повторениях, 1.221E-05 ms per]
  • coallesce 1.14x 1387 тиков (0.1387 мс) [в 10K повторениях, 1.387E-05 ms per]
  • строка + 1.16x 1415 тиков (0.1415 мс) [в повторах 10K, 1.415E-05 ms per]
  • str.Concat 1.16x 1420 тиков (0.142 мс) [в повторениях 10K, 1.42E-05 ms per]
  • Конвертировать 1,58x 1931 тиков (0.1931 мс) [в 10K повторений, 1.931E-05 ms per]
  • str.Format 5.45x 6655 тиков (0,6655 мс) [в 10K повторениях, 6.655E-05 ms per]

Строка

  • nullcheck 1.00x 1190 тиков (0.119 мс) [в 10K повторениях, 1.19E-05 ms per]
  • Конвертировать 1,01x 1200 тиков (0.12 мс) [в 10K повторений, 1.2E-05 ms per]
  • строка + 1.04x 1239 тиков (0.1239 мс) [в 10K повторениях, 1.239E-05 ms per]
  • coallesce 1.20x 1423 тиков (0.1423 мс) [в повторах 10K, 1.423E-05 ms per]
  • str.Concat 4.57x 5444 тиков (0.5444 мс) [в 10K повторениях, 5.444E-05 ms per]
  • str.Format 5.67x 6750 тиков (0.675 мс) [в повторах 10K, 6.75E-05 ms per]

Ответ 12

Хотя это старый вопрос и ОП попросил С#, я хотел бы поделиться решением VB.Net для тех, кто работает с VB.Net, а не с С#:

Dim myObj As Object = Nothing
Dim s As String = If(myObj, "").ToString()

myObj = 42
s = If(myObj, "").ToString()

К сожалению, VB.Net не разрешает использовать переменную? -operator после переменной, поэтому myObj?.ToString недопустим (по крайней мере, не в .Net 4.5, который я использовал для тестирования решения). Вместо этого я использую If, чтобы вернуть пустую строку, если myObj ist Nothing. Таким образом, первый Tostring-Call возвращает пустую строку, а второй (где myObj не является Nothing) возвращает "42".