nullの可能性があるオブジェクトに対してToStringを実行する方法


97

以下を行う簡単な方法はありますか?

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

私は次のことができることはわかっていますが、実際にはハックと見なしています。

String s = "" + myObj;

Convert.ToString()がこれに対して適切なオーバーロードを持っているとすばらしいでしょう。


3
私は最初のものに問題はないと思います。2番目がハックであると考える場合、最善の策は、nullチェックを実行するユーティリティ関数を記述することです。
Nick Larsen、

plzは

3
string.Format( "{0}"、myObj)はnull値を受け入れます。
Holstebroe

3
C#6.0では、theText?.ToString()やtheText?.Trim()などのnull条件演算子を使用できるようになりました
Santosh

2
この回答に よれConvert.ToString()ば、あなたが下に書いた最初のことを正確に行います。
drzaus 2017

回答:


175

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

これはコンパイルされますか?合体オペレータはタイプをチェックしませんか?
Nick Larsen、

1
合体は最も一般的でない型を使用するため、(object ?? string)はオブジェクトを返すため、機能します。しかし、どのクラスを選択するか決定できないため、これはインターフェースでは機能しないと思います(クラスごとに複数のインターフェースが許可されているため)。
codymanix、

1
私が本当に望んでいた解決策ではありませんが、それを受け入れます
codymanix

4
そのオブジェクトキャストとしての反対投票はひどく醜く、ボクシングを伴います。
シュタイナー

1
c#6への最初のオプションは非常にエレガントです
Alexandre N.

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

string.Formatはnullを空の文字列としてフォーマットし、null以外のオブジェクトでToString()を呼び出します。私の理解では、これはあなたが探していたものです。


3
私は個人的にこれが好きではありません。コードはString s = myObj == nullよりもわずかに短い場合があります。"":myObj.ToString()ですが、メソッドの背後にある理由を完全に隠しています。
AGuyCalledGerald 2014

これはマイクロ最適化であると認められますが、それだけでよりも約5倍長くかかります"" + myObj。しかし、それは余分な文字列を作成することを読んだ。 str.Concat(myObj)正常に動作するようで、「さらに高速」です。
drzaus 2017

17

Convert.ToString()がこれに対して適切なオーバーロードを持っているとすばらしいでしょう。

行われていますConvert.ToString(Object value).NET 2.0以降(約5年前に頼まれました。この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();
    }
}

以下は画面に何も書き込まず、例外をスローしません。

        string value = null;

        Console.WriteLine(value.ToStringOrEmpty());

拡張メソッド呼び出しは、nullの通常のチェックを省略しますか?
Matti Virkkunen、2010年

2
また、「{0}」を入力する必要がなく、実行していることを説明するメソッド名を選択できます。これは、これを何度も行う場合に特に便利です。メソッドにToStringOrEmptyWhenNullという名前を付けることもできます。
Pieter van Ginkel

2
OP string s = "" + myObj;がハックだと考える場合、nullオブジェクトで関数を呼び出すと、同じボートに分類されます。私はこれに反対票を投じますが、それは当面の問題を解決します、私は使用法に同意しません。NullReferenceException拡張メソッドであっても、nullオブジェクトはをスローする必要があります。
Nick Larsen

2
@NickLarsen:ほとんどの場合私はあなたに同意しますが、単純なメソッド呼び出しの便利さを望むだけの場合もあります。メソッド名は、の提案のように、null参照がOKであるというヒントを与えるはずですToStringOrEmptyWhenNull
ジョルダン

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の合体演算子は少し明確ではないと思いますが、それを使用しても問題はありません。
シュタイナー

@Pieter公正です。しかし、そうです。問題は、「以下を実行する簡単な方法はありますか:...」です。その正確な方法は簡単です!
シュタイナー、2010年

この方法はハックであると私は決して言いませんでした。私の質問をもう一度読んでください。この機能を備えたフレームワークの小さな機能を見逃しているだけです。
codymanix、

4
string s = String.Concat(myObj);

私が推測する最短の方法であり、パフォーマンスのオーバーヘッドも無視できます。コードの読者には意図が何であるかは明確ではありませんが、覚えておいてください。


2
これは "" + myObjの明示的な形式ですが、ここで何が行われているのかを伝えるのはさらに悪いことです。とにかく面白い。
codymanix、

@codymanix私はそれは同じだとは思いません- Concat実際には、下でnullチェックを実行してstring.Emptyor を返しますarg0.ToString()
drzaus 2017

2

実は私はあなたが何をしたいのか理解できませんでした。私が理解しているように、このコードはこのように別の方法で書くことができます。あなたはこれを求めていますか?詳細を説明できますか?

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

確かに私はこのように書くことができますが、簡単な小さな関数呼び出しが必要です
。.NETBCLに

IsNullOrEmpty()メソッドがあるときに本当に関数が必要ですか?
Serkan Hekimoglu

その点について、私は常に合体演算子が流暢な式のnull参照にヒットしたときに次に失敗することを望んでいましたが、それがひどい考えである理由を完全に理解しています。それを可能にするオーバーライドもいいでしょう。
Nick Larsen、

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

2

私は私の答えに打ちのめされるかもしれませんが、とにかくここに行きます:

私は単に書きます

文字列s = "" if(myObj!= null){x = myObj.toString(); }

三項演算子を使用することによるパフォーマンスの見返りはありますか?頭の上がわからない。

そして明らかに、上記の誰かが述べたように、この動作をsafeString(myObj)などのメソッドに入れて再利用することができます。


OMGオブジェクトがnullの場合、それに対してToString()を呼び出しますか?
codymanix、

さあ、それはタイプミスです。最初の=を!それを正しくするために。しかし、あなたは本当にタイプミスのために私を-1にするつもりですか?
ジェイデル

2

同じ問題があり、オブジェクトを文字列にキャストするだけで解決しました。文字列はnullになる可能性があるため、これはnullオブジェクトにも機能します。null文字列を絶対に使いたくない場合を除き、これは問題なく機能します。

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(...)null文字列を保持するがです。

結果

オブジェクト

  • nullcheck 1.00x 1221ティックの経過(0.1221ミリ秒)[10K反復で、1.221E-05ミリ秒あたり]
  • 合体1.14x 1387ティックの経過(0.1387ミリ秒)[1万回で1.387E-05ミリ秒]
  • 文字列+ 1.16x 1415ティックの経過(0.1415ミリ秒)[10K反復で、1.415E-05ミリ秒あたり]
  • str.Concat 1.16x 1420ティックの経過(0.142ミリ秒)[10K反復で、1.42E-05ミリ秒あたり]
  • 変換された1.58x 1931ティックの経過(0.1931ミリ秒)[1万レップ、1.931E-05ミリ秒あたり]
  • str.Format 5.45x 6655ティックの経過(0.6655ミリ秒)[10K反復で、6.655E-05ミリ秒あたり]

ストリング

  • nullcheck 1.00x 1190ティックの経過(0.119ミリ秒)[1万レップ、1.19E-05ミリ秒あたり]
  • 経過した1.01x 1200ティックの変換(0.12ミリ秒)[1万レップ、1.2E-05ミリ秒あたり]
  • 文字列+ 1.04x 1239ティックの経過(0.1239ミリ秒)[10K表現、1.239E-05ミリ秒あたり]
  • 合体1.20x 1423ティックの経過(0.1423ミリ秒)[1万回で1.423E-05ミリ秒]
  • str.Concat 4.57x 5444ティックの経過(0.5444ミリ秒)[10K反復で、5.444E-05ミリ秒あたり]
  • str.Format 5.67x 6750ティックの経過(0.675ミリ秒)[10K反復で、6.75E-05ミリ秒あたり]

1

Holstebroeのコメントが最良の答えです。

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

もし myObjがnullの、Formatは空の文字列値をそこに配置します。

また、1行の要件も満たし、読みやすくなっています。


はい、しかしコードは明確ではありません。何人の開発者があなたが何を成し遂げようとしているのか知っていますか?
AGuyCalledGerald 2014

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では無効です)。代わりに、ifを使用して、myObjがNothingの場合に空の文字列を返します。したがって、最初のTostring-Callは空の文字列を返し、2番目の(myObjがNothingではない)は "42"を返します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.