?? 空の文字列を結合しますか?


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

これを行うための組み込みの方法はありません。ただし、拡張メソッドで文字列またはnullを返すようにすることもできます。これにより、合体演算子が機能します。これは奇妙なことですが、私は個人的にあなたの現在のアプローチを好みます。

すでに拡張メソッドを使用しているので、値またはデフォルトを返すメソッドを作成しないでください。

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

7
私はあなたが正しいと思います、そしてこれはまだ読める現在利用可能な最もきれいな解決策です。でも???、C#5のオペレーターのような人は知っています。
Nick Craver

2
そして何を??? オペレーターは?nullに加えてデフォルト値を取得しますか?せいぜい非常に複雑に聞こえる
bevacqua '25 / 07/25

1
多分ラムダ式で?例えば:...その後、「アイテム」がNULL可能であると仮定 item ?? x=> x.ToString() : null;
アイザックLlopis

@IsaacLlopisはOPの元のスニペットよりも乱雑に見えます
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 14

値をまとめずに、空でない値を選択するだけで、なぜこのコアレスを呼び出すのですか?それは紛らわしい名前の男です。
Jimmyt1988

8
Coalesceは、多くのデータベースで同じ操作を行うために使用される用語です(最初の非null値を見つけます)。文字列を結合することは連結です。
キャメロンフォワード

あなたがしている場合のベストアンサー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
"CoalesceTo"に変更しましたが、 "Coalesce"という用語を使用しています。これは、nullの合体演算子(??)の意図に似ています。
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を使用しないのはなぜですか。
ウェストン

1
codepublic static string Coalesce(this string @this、string @default = ""){return(@this == null || String.IsNullOrWhiteSpace(@this))?@default:@this; }
2011年

6

ヌル結合演算子の利点の1つは、短絡することです。最初の部分がnullでない場合、2番目の部分は評価されません。これは、フォールバックに高価な操作が必要な場合に役立ちます。

私は次のようになりました:

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

よく使っています。最初に使用しないと生きていけない「​​ユーティリティ」関数の1つ:-)


彼らがLINQを使用している理由を理解していないと思います。パラメーターは呼び出しの前に評価されるs2.Coalesce(s3)ため、不要な場合でも実行されます。NullIfEmpty()拡張機能とを使用する方がよい??
NetMage

@NetMage LINQのバージョンは、提示したバージョンよりもパフォーマンスがはるかに低いことを保証できます。必要に応じて、これをテストする簡単なベンチマークを作成できます。github.com/dotnet/BenchmarkDotNetを使用して、ベンチマークコードを作成する際によくある落とし穴を防ぐことを勧めします。
Loudenvier

0

QQQはこれのために次の拡張メソッドの簡潔さが好きですが、もちろん演算子は好きですか?方が良いだろう。しかし、2つだけでなく3つの文字列オプション値を比較できるようにすることで、これを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、それはのように、デフォルトのシナリオまたは2のためにそれをしない方が良いでしょうparamsあなたは、デフォルトの1つまたは2つの入力を持っている時に不割り当てられる配列の原因。その後は理にかなっています。
Nicholas Petersen
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.