null 가능성이있는 개체에 대해 ToString을 수행하는 방법은 무엇입니까?


99

다음을 수행하는 간단한 방법이 있습니까?

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

다음을 수행 할 수 있다는 것을 알고 있지만 실제로는 해킹으로 간주합니다.

String s = "" + myObj;

Convert.ToString ()에 적절한 오버로드가 있으면 좋을 것입니다.


3
나는 첫 번째 것에서 잘못된 것이 없다고 생각합니다. 두 번째를 해킹이라고 생각한다면 null 검사를 수행하는 유틸리티 함수를 작성하는 것이 가장 좋습니다.
Nick Larsen

plz 귀하의 질문에 대해 더 정확할 수 있습니까
FosterZ

3
string.Format ( "{0}", myObj)는 null 값을 허용합니다.
Holstebroe

3
C # 6.0에서는 이제 theText? .ToString () 또는 theText? .Trim ()과 같은 null 조건부 연산자를 사용할 수 있습니다
Santosh

2
이 답변 Convert.ToString() 은 아래에 쓴 정확하게 첫번째 일을한다.
drzaus

답변:


179

C # 6.0 편집 :

C # 6.0에서는 이제 간결하고 캐스트없는 버전의 orignal 메서드를 사용할 수 있습니다.

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();
}

이것이 컴파일됩니까? 통합 연산자가 유형을 확인하지 않습니까?
Nick Larsen

1
(object ?? string)은 합체가 가장 덜 일반적인 유형을 사용하기 때문에 객체를 반환하기 때문에 작동합니다. 그러나 어떤 인터페이스를 선택할지 결정할 수 없기 때문에 이것이 인터페이스에서 작동하지 않을 것이라고 생각합니다 (클래스 당 여러 인터페이스가 허용되기 때문에).
codymanix

1
내가
바라던

4
그 개체 캐스트에 대한 반대 투표는 매우 추하고 권투를 포함합니다.
steinar 2011 년

1
C # 6에 대한 첫 번째 옵션은 매우 우아
알렉산더 N.

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

string.Format은 null을 빈 문자열로 형식화하고 null이 아닌 객체에서 ToString ()을 호출합니다. 내가 이해했듯이 이것은 당신이 찾고 있던 것입니다.


3
나는 개인적으로 이것을 좋아하지 않는다. 코드는 String s = myObj == null? "": myObj.ToString (),하지만 메서드 뒤에있는 이유를 완전히 숨 깁니다.
AGuyCalledGerald

이는 마이크로 최적화이지만 "" + myObj. 그러나 나는 여분의 문자열을 만드는 것을 읽었습니다. str.Concat(myObj)잘 작동하는 것 같고 "더 빠릅니다".
drzaus

18

Convert.ToString ()에 적절한 오버로드가 있으면 좋을 것입니다.

가있었습니다 Convert.ToString(Object value)닷넷 2.0 이후 (약 오년 전에 질문을 받았다이 Q.) 당신이 원하는 것을 정확히 할 나타납니다 :

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

내가 여기서 정말 명백한 것을 놓치고 있거나 잘못 해석하고 있습니까?


1
당신은하지 않습니다. 이유는 간단는 :) 복잡 할 수있을 때
alex.peter

13

확장 메서드를 사용하면 다음을 수행 할 수 있습니다.

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

다음은 화면에 아무것도 쓰지 않고 예외를 throw하지 않습니다.

        string value = null;

        Console.WriteLine(value.ToStringOrEmpty());

확장 메서드 호출은 일반적인 null 검사를 생략합니까 ...?
Matti Virkkunen

2
"{0}"을 (를) 입력 할 필요가 없으며 수행중인 작업을 설명하는 메서드 이름을 선택할 수 있음을 추가합니다. 이 작업을 여러 번 수행 할 때 특히 유용합니다. ToStringOrEmptyWhenNull 메서드의 이름을 지정할 수도 있습니다.
Pieter van Ginkel

2
OP가 그것이 string s = "" + myObj;hackish 라고 생각 하면 null 객체에 대한 함수를 호출하는 것은 동일한 보트에 속해야합니다. 나는 이것을 반대표를 던지지 만 그것은 당면한 문제를 해결합니다. 나는 단지 사용법에 동의하지 않습니다. NullReferenceException확장 메서드에서도 Null 개체는을 throw해야 합니다.
Nick Larsen

2
@NickLarsen : 대부분의 경우 동의하지만 때로는 간단한 메서드 호출의 편리함을 원합니다. 메서드 이름은에 대한 제안과 같이 null 참조가 괜찮다는 힌트를 제공해야합니다 ToStringOrEmptyWhenNull.
Jordão

3
확장 메서드는 "첫 번째"매개 변수 ( this매개 변수)가 구문 적 설탕 일 뿐이므로 발생하지 않습니다 . 즉이 x.SomeExtensionMethod()에 대한 문법 설탕입니다 SomeStaticClass.SomeExtensionMethod(x);따라서, 때 x입니다 null우리는의 메소드 호출을 시도하지 않는 null개체를 오히려 통과 null정적 방법으로 개체를. 해당 메소드가 null매개 변수를 확인 하고이를 만났을 때 발생 하는 경우에만 확장 메소드가 null객체 에서 "호출"됩니다 .
jason

7

나는 이것에 동의하지 않는다 :

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

어떤 식 으로든 해킹입니다. 명확한 코드의 좋은 예라고 생각합니다. 달성하려는 것이 무엇인지 그리고 null을 기대하고 있다는 것은 절대적으로 분명합니다.

최신 정보:

나는 당신이 이것이 해킹이라고 말하지 않았 음을 알았습니다. 그러나 당신이이 방법이 갈 길이 아니라고 생각한다는 것은 질문에 내포되어 있습니다. 제 생각에는 확실히 가장 명확한 해결책입니다.


그는이 방법이 해킹이라고 말하지 않았습니다. 사실 그는 그것이 단순하지 않다는 것을 암시하는 것 외에는 무엇이 잘못되었는지 말하지 않았습니다. 나는이 방법에 아무런 문제가 없다고 생각한다. +1. 이렇게 할 것이기 때문입니다.
Mark Byers

나는 OP에 동의합니다 .C #에는 이미 null 병합 연산자가 있습니다. 아래 내 게시물을 참조하십시오.
Andrew Hanlon

이 경우 null 병합 연산자가 약간 덜 명확하다고 생각하지만 사용하는 것만으로도 괜찮습니다.
steinar

@Pieter 충분히 공정합니다. 하지만 그렇습니다. 질문은 "다음을 수행하는 간단한 방법이 있습니까 : ..."입니다. 정확한 방법은 간단합니다!
steinar

나는 방법이 해킹 이라고 말한 적이 없다 . 내 질문을 다시 읽어주세요. 이 기능을 가진 프레임 워크의 작은 기능 만 놓친다.
codymanix

4
string s = String.Concat(myObj);

내가 추측하는 가장 짧은 방법이며 성능 오버 헤드도 무시할 수 있습니다. 의도가 무엇인지 코드 독자에게 명확하지 않을 수 있지만 명심하십시오.


2
이것은 ""+ myObj의 명시적인 형식이지만 여기서 무슨 일이 벌어지고 있는지 말하기에는 더 나쁩니다. 어쨌든 흥미 롭습니다.
codymanix

@codymanix 나는 그것이 동일하다고 생각하지 않습니다. Concat실제로 아래에 null 검사를 수행하고 string.Empty또는 arg0.ToString()약간 더 성능이 좋은 것 같습니다 (여기서는 ms를 이야기하고 있습니다).
drzaus

2

사실 나는 당신이 무엇을하고 싶은지 이해하지 못했습니다. 내가 이해했듯이이 코드를 이와 같은 다른 방식으로 작성할 수 있습니다. 이건 물어 보는 건가요? 더 설명해 주시겠습니까?

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

물론 이렇게 작성할 수 있지만 간단한 작은 함수 호출을 원합니다. .NET BCL에 이와 같은 것이없는 이유가 궁금합니다
codymanix

IsNullOrEmpty () 메서드를 사용하는 동안 정말 함수가 필요합니까?
Serkan Hekimoglu

그 메모에서 나는 항상 유창한 표현에서 null 참조에 도달하면 병합 연산자가 다음에 실패하기를 원했지만 왜 그것이 끔찍한 아이디어인지 완전히 이해합니다. 그렇게 할 수있는 재정의도 좋을 것입니다.
Nick Larsen

1
string s = string.IsNullOrEmpty(myObj) ? string.Empty : myObj.ToString();
Nick Larsen

2

나는 내 대답에 맞을 수도 있지만 어쨌든 여기에 간다.

나는 단순히 쓸 것이다

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

삼항 연산자를 사용하여 성능 측면에서 보답이 있습니까? 나는 내 머리 꼭대기에서 모른다.

그리고 분명히 위에서 언급했듯이 재사용을 허용하는 safeString (myObj)와 같은 메소드에이 동작을 넣을 수 있습니다.


객체가 null이면 OMG에서 ToString ()을 호출합니까?
codymanix

어서 오타입니다. 나는 첫 번째 =를! 수정합니다. 하지만 당신은 정말 오타로 나에게 -1을 할 건가요?
jaydel

2

나는 같은 문제가 있었고 단순히 객체를 문자열로 캐스팅하여 해결했습니다. 이것은 문자열이 널이 될 수 있기 때문에 널 객체에서도 작동합니다. 절대적으로 널 문자열을 원하지 않는 한, 이것은 잘 작동합니다.

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

가장 짧고 최상의 솔루션. (OBJ1 ?? "")로 .toString ()는 실제로 첫째 : 너무 문자열로 OBJ1 캐스트
TPAKTOPA

2

다양한 옵션을 요약 한 일부 (속도) 성능 테스트, 정말 중요하지는 않습니다. #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.1221ms) [10K 반복에서, 1.221E-05ms 당]
  • 합체 1.14x 1387 틱 경과 (0.1387ms) [10K 반복에서, 당 1.387E-05ms]
  • 문자열 + 1.16x 1415 틱 경과 (0.1415ms) [10K 반복에서, 1.415E-05ms 당]
  • str.Concat 1.16x 1420 틱 경과 (0.142ms) [10K 반복에서, 1.42E-05ms 당]
  • 경과 된 1.58x 1931 틱 (0.1931ms) 변환 [10K 반복에서, 1.931E-05ms 당]
  • str. Format 5.45x 6655 틱 경과 (0.6655ms) [10K 반복, 6.655E-05ms 당]

  • nullcheck 1.00x 1190 틱 경과 (0.119ms) [10K 반복에서, 1.19E-05ms 당]
  • 경과 된 1.01x 1200 틱 (0.12ms) 변환 [10K 반복에서, 당 1.2E-05ms]
  • 문자열 + 1.04x 1239 틱 경과 (0.1239ms) [10K 반복에서, 당 1.239E-05ms]
  • 합체 1.20x 1423 틱 경과 (0.1423ms) [10K 반복에서, 당 1.423E-05ms]
  • str.Concat 4.57x 5444 틱 경과 (0.5444ms) [10K 반복, 5.444E-05ms 당]
  • str. Format 5.67x 6750 틱 경과 (0.675ms) [10K 반복, 6.75E-05ms 당]

1

Holstebroe의 의견이 가장 좋은 답변이 될 것입니다.

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

경우 myObj널 (null)이며, 형식이 빈 문자열 값을 배치합니다.

또한 한 줄 요구 사항을 충족하며 읽기 쉽습니다.


예,하지만 코드가 명확하지 않습니다. 동료 개발자 중 얼마나 많은 사람들이 당신이 이루고자하는 일을 알고있을 것입니까?
AGuyCalledGerald

0

이것은 오래된 질문이고 OP가 C #을 요청했지만 C #이 아닌 VB.Net을 사용하는 사람들을 위해 VB.Net 솔루션을 공유하고 싶습니다.

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에서는 아님). 대신 myObj가 Nothing 인 경우 빈 문자열을 반환하기 위해 If를 사용합니다. 따라서 첫 번째 Tostring-Call은 빈 문자열을 반환하고 두 번째 (myObj가 Nothing이 아닌 경우)은 "42"를 반환합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.