it-swarm.com.ru

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

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

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

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

String s = "" + myObj;

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

76
codymanix

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

С C # 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();
}
140
Andrew Hanlon
string.Format("{0}", myObj);

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

39
Holstebroe

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

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

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

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

12
Rob Gilliam

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

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

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

        string value = null;

        Console.WriteLine(value.ToStringOrEmpty());
12
Pieter van Ginkel

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

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

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

Обновление:  

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

7
steinar
string s = String.Concat(myObj);

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

4
herzmeister

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

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

Я мог бы быть избит за мой ответ, но здесь все равно идет:

Я бы просто написал 

строка s = "" if (myObj! = null) { x = myObj.toString (); }

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

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

2
jaydel

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

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

Если myObj равен нулю, Format помещает туда значение пустой строки.

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

1
jp2code

Некоторые (быстродействующие) тесты производительности, суммирующие различные варианты, не то, что это действительно имеет значение #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 мс в] 
  • coallesce 1,14x 1387 тиков прошло (0,1387 мс) [в 10K повторений, 1,387E-05 мс в] 
  • истекла строка + 1,16x 1415 тактов (0,1415 мс) [в 10 000 повторений, 1,415E-05 мс за] 
  • str.Concat Прошло 1,16x1420 тиков (0,142 мс) [за 10 000 повторений, 1,42E-05 мс за] 
  • Преобразование 1,58х 1931 прошедших тактов (0,1931 мс) [за 10 000 повторений, 1,931E-05 мс за] 
  • str.Format 5,45x 6655 тактов (0,6655 мс) [в 10 000 повторений, 6,655E-05 мс в]

Строка

  • nullcheck 1,00x 1190 тактов прошло (0,119 мс) [за 10 000 повторений, 1,19E-05 мс за] 
  • Преобразование 1.01x 1200 тиков прошло (0,12 мс) [в 10K повторений, 1,2E-05 мс за] 
  • истекла строка + 1,04x 1239 тактов (0,1239 мс) [за 10 000 повторений, 1,239E-05 мс за] 
  • coallesce 1,20 х 1423 тиков прошло (0,1423 мс) [в 10K повторений, 1,423E-05 мс в] 
  • str.Concat: 4,57x 5444 такта (0,5444 мс) [за 10 000 повторений, 5.444E-05 мс за] 
  • str.Format 5,67x 6750 тактов (0,675 мс) [в 10K повторений, 6,75E-05 мс в] 
1
drzaus

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

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

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

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

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

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

0
Sascha