?? 빈 문자열에 대한 병합?


165

내가 점점 더 많이하고있는 것은 문자열이 비어 있거나 (있는 ""또는 null 인) 조건부 연산자를 확인하는 것입니다.

현재 예 :

s.SiteNumber.IsNullOrEmpty() ? "No Number" : s.SiteNumber;

이것은 확장 방법 일 뿐이며 다음과 같습니다.

string.IsNullOrEmpty(s.SiteNumber) ? "No Number" : s.SiteNumber;

비어 있고 null ??이 아니기 때문에 트릭을 수행하지 않습니다. 의 string.IsNullOrEmpty()버전은 ??완벽한 솔루션이 될 것입니다. 나는 이것을하는 더 깨끗한 방법이 있어야한다고 생각하지만 (나는 희망한다!), 나는 그것을 찾지 못했습니다.

.Net 4.0에만있는 사람 이라도이 작업을 수행하는 더 좋은 방법을 알고 있습니까?


11
약간의 감탄을주기 위해 F #에서 사용자 정의 임시 바이너리 (및 해당 단항) 연산자를 쉽게 정의 할 수 있습니다. 여기 let (|?) x y = if String.IsNullOrEmpty(x) then y else x와 같이 사용하십시오 s.SiteNumber |? "No Number".
Stephen Swensen

답변:


72

이를위한 기본 제공 방법은 없습니다. 그러나 확장 메소드가 문자열 또는 널을 리턴하도록하여 통합 연산자가 작동 할 수 있습니다. 그러나 이것은 이상 할 것입니다. 개인적으로 귀하의 현재 접근 방식을 선호합니다.

이미 확장 메서드를 사용하고 있으므로 값이나 기본값을 반환하는 확장 메서드를 만드는 것이 어떻습니까?

string result = s.SiteNumber.ConvertNullOrEmptyTo("No Number");

7
나는 당신이 옳다고 생각하며, 이것은 여전히 ​​읽을 수있는 가장 깨끗한 솔루션입니다. ???그래도 C # 5 의 연산자 와 같은 것을 알고 싶습니다 .
Nick Craver

2
그리고 무엇입니까 ??? 운영자? null 외에도 기본값을 사용합니까? 매우 복잡하게 들린다
bevacqua

1
람다 식으로? 예를 들어 : "항목"이 널 입력 가능하다고 가정하면 ... item ?? x=> x.ToString() : null;
Isaac Llopis

@IsaacLlopis 그 영업의 원래 조각보다 더 찾고 지저분한 - 어 끝
maksymiuk

133

C #은 이미 우리가 값을 대체 할 수 있습니다 null??. 따라서 빈 문자열을로 변환하는 확장명 만 있으면 null다음과 같이 사용합니다.

s.SiteNumber.NullIfEmpty() ?? "No Number";

확장 클래스 :

public static class StringExtensions
{
    public static string NullIfEmpty(this string s)
    {
        return string.IsNullOrEmpty(s) ? null : s;
    }
    public static string NullIfWhiteSpace(this string s)
    {
        return string.IsNullOrWhiteSpace(s) ? null : s;
    }
}

44

나는 이것이 오래된 질문이라는 것을 알고 있지만 대답을 찾고 있었고 위의 어느 것도 내 필요와 내가 사용한 것을 충족시키지 못했습니다.

private static string Coalesce(params string[] strings)
{
    return strings.FirstOrDefault(s => !string.IsNullOrEmpty(s));
}

용법:

string result = Coalesce(s.SiteNumber, s.AltSiteNumber, "No Number");

편집 : 이 함수를 작성하는 훨씬 간단한 방법은 다음과 같습니다.

static string Coalesce(params string[] strings) => strings.FirstOrDefault(s => !string.IsNullOrEmpty(s));

1
나는 좋아하지만 컴파일러 오류를 수정하고 좀 더 작게 만들어야했습니다.
gregmac

이 Coalesce를 사용하여 값을 가져 오지 않고 왜 비어 있지 않은 값을 선택해야합니까? 혼란스러운 이름의 친구입니다.
Jimmyt1988

8
Coalesce는 많은 데이터베이스에서 동일한 작업을 수행하기 위해 사용되는 용어이므로 (널이 아닌 값을 먼저 찾습니다) 문자열을 결합하면 연결됩니다.
카메론 포워드

최고의 답변using System.Linq
JoePC

우아하고 훌륭합니다.
마리아노 루이스 빌라

16

사용하고 싶은 몇 가지 유틸리티 확장이 있습니다.

public static string OrDefault(this string str, string @default = default(string))
{
    return string.IsNullOrEmpty(str) ? @default : str;
}

public static object OrDefault(this string str, object @default)
{
    return string.IsNullOrEmpty(str) ? @default : str;
}

편집 : sfsr 의 답변에서 영감을 얻어 지금부터 도구 상자 에이 변형을 추가 할 것입니다.

public static string Coalesce(this string str, params string[] strings)
{
    return (new[] {str})
        .Concat(strings)
        .FirstOrDefault(s => !string.IsNullOrEmpty(s));
}

1
"Coalesce"라는 용어를 사용했지만 null 통합 연산자 (??)의 의도와 더 유사하기 때문에 "Coalesce"라는 용어를 사용하고 있습니다.
llaughlin

매개 변수 의 @접두사 는 무엇을 @default합니까? 나는 전에 그것을 본 적이 없다.
Drew Chapin

3
@druciferre- defaultC #에서 예약 키워드이지만 변수 이름 으로 사용할 수 있습니다 .
Justin Morgan

1
@ Jimmyt1988-표준 T-SQL COALESCE 함수 와 비슷하기 때문 입니다.
Justin Morgan

1
@ Jimmyt1988-또한 임의 길이 목록에서 비어 있지 않은 첫 번째 기능을 구체적으로 선택하기 때문 입니다. 미묘한 세부 사항이지만 T-SQL 함수는 동일한 방식으로 작동합니다. 이름은 문서의 유무에 관계없이 해당 기능을 아는 사람에게 직관적입니다.
Justin Morgan

6

이전에 제안 된 것보다 약간 빠른 확장 방법 :

public static string Fallback(this string @this, string @default = "")
{
    return (@this == null || @this.Trim().Length == 0) ? @default : @this;
}

11
자르고 길이를 지정하는 대신 IsNullOrWhitespace 를 사용하지 않겠습니까 ?
weston December

1
code공개 정적 문자열 Coalesce (이 문자열 @this, 문자열 @default = "") {return (@this == null || String.IsNullOrWhiteSpace (@this))? @default : @this; }
paul-2011

6

널 병합 연산자의 장점 중 하나는 단락되는 것입니다. 첫 번째 부분이 null이 아닌 경우 두 번째 부분은 평가되지 않습니다. 폴백에 값 비싼 작업이 필요한 경우에 유용 할 수 있습니다.

나는 결국 :

public static string Coalesce(this string s, Func<string> func)
{
    return String.IsNullOrEmpty(s) ? func() : s;
}

용법:

string navigationTitle = model?.NavigationTitle.
    Coalesce(() => RemoteTitleLookup(model?.ID)). // Expensive!
    Coalesce(() => model?.DisplayName);

6

문자열이 비어 있으면 항상 null을 반환하는 NullIfEmpty 확장 메서드를 사용하면됩니다. (Null Coalescing Operator)가 정상적으로 사용됩니다.

public static string NullIfEmpty(this string s)
{
    return s.IsNullOrEmpty() ? null : s;
}

그러면 허용됩니다 ?? 정상적으로 사용되며 체인을 쉽게 읽을 수 있습니다.

string string1 = string2.NullIfEmpty() ?? string3.NullIfEmpty() ?? string4;

3

문자열 확장 메서드 ValueOrDefault ()는 어떻습니까

public static string ValueOrDefault(this string s, string sDefault)
{
    if (string.IsNullOrEmpty(s))
        return sDefault;
    return s;
}

문자열이 비어 있으면 null을 반환합니다.

public static string Value(this string s)
{
    if (string.IsNullOrEmpty(s))
        return null;
    return s;
}

그래도 이러한 솔루션을 시도하지 않았습니다.


2
나는 옵션 # 1을 좋아하지만 Or ()와 같은 의미 론적이라고 부를 수는 있지만 "string s = s.SiteNumber.Or ("Default ");"
jvenema

2
...OrDefault()프레임 워크의 나머지 ...OrDefault()메소드 처럼 동작하지 않으면 무언가를 호출하는 것이 혼란 스러울 수 있습니다 . 그렇 든 없든 MS는 사용자 지정 메서드에서 해당 동작을 명명하고 이탈하는 것이 API 사용자에게 불필요하게 혼동된다는 특별한 의미를 부여했습니다.
mattmc3

3

내 자신의 문자열 Coalesce 확장 방법을 사용하고 있습니다. 여기에있는 사람들은 LINQ를 사용하고 시간 집약적 인 작업을 위해 리소스를 낭비하고 있기 때문에 (나는 그것을 꽉 찬 루프에서 사용하고 있습니다) 공유 할 것입니다.

public static class StringCoalesceExtension
{
    public static string Coalesce(this string s1, string s2)
    {
        return string.IsNullOrWhiteSpace(s1) ? s2 : s1;
    }
}

나는 그것이 매우 간단하다고 생각하며 null 문자열 값을 신경 쓰지 않아도됩니다. 다음과 같이 사용하십시오.

string s1 = null;
string s2 = "";
string s3 = "loudenvier";
string s = s1.Coalesce(s2.Coalesce(s3));
Assert.AreEqual("loudenvier", s);

나는 그것을 많이 사용합니다. "유틸리티"기능 중 하나는 먼저 사용하지 않고는 살 수 없습니다 :-)


나는 그들이 LINQ를 사용하는 이유를 이해하지 못한다고 생각하며, 매개 변수가 호출 전에 평가되므로 s2.Coalesce(s3)필요하지 않은 경우에도 실행됩니다. NullIfEmpty()확장 프로그램 을 사용하는 것이 좋습니다 ??.
NetMage

@NetMage LINQ 버전이 내가 제시 한 것보다 성능이 훨씬 떨어진다는 것을 보증 할 수 있습니다. 원하는 경우 간단한 벤치 마크를 만들어이를 테스트 할 수 있습니다. 벤치마킹 코드를 작성할 때 일반적인 함정을 피하기 위해 github.com/dotnet/BenchmarkDotNet 을 사용하는 것이 좋습니다 .
Loudenvier

0

QQQ물론 다음과 같은 확장 방법의 간결함이 마음에 듭니다 . 더 좋을 것입니다. 그러나 두 개뿐 아니라 세 개의 문자열 옵션 값을 비교할 수 있으므로 1을 처리 할 수 ​​있습니다.

#region QQ

[DebuggerStepThrough]
public static string QQQ(this string str, string value2)
{
    return (str != null && str.Length > 0)
        ? str
        : value2;
}

[DebuggerStepThrough]
public static string QQQ(this string str, string value2, string value3)
{
    return (str != null && str.Length > 0)
        ? str
        : (value2 != null && value2.Length > 0)
            ? value2
            : value3;
}


// Following is only two QQ, just checks null, but allows more than 1 string unlike ?? can do:

[DebuggerStepThrough]
public static string QQ(this string str, string value2, string value3)
{
    return (str != null)
        ? str
        : (value2 != null)
            ? value2
            : value3;
}

#endregion

짧은 이름을 좋아한다면이라고 부를 수 있으며 다른 답변과 마찬가지로 키워드를 Or사용하여 params여러 매개 변수에 대한 중복 정의를 피할 수 있습니다.
Chiel ten Brinke

아이디어 주셔서 감사합니다. 그 후 오랫동안이 이름을 "FirstNotNull"로 바꿨습니다. 에 params, 그것으로, 기본 시나리오 이틀 동안 그렇게하지 않는 것이 좋습니다 것입니다 params만 기본 하나 또는 두 개의 입력이있을 때 불필요하게 할당 할 수 배열됩니다. 그 후 의미가 있습니다.
Nicholas Petersen
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.