105

私は C# を勉強していますToStringが、次の例に示すように、オーバーライドのポイントとメリットは何だろうと考えています。

これは、オーバーライドなしで一般的な方法を使用して、より簡単な方法で行うことができますか?

public string GetToStringItemsHeadings
{
    get { return string.Format("{0,-20} {1, -20}", "Office Email", "Private Email"); }
}


public override string ToString()
{
    string strOut = string.Format("{0,-20} {1, -20}", m_work, m_personal);
    return strOut;
}
4

17 に答える 17

130

.NET 開発シリーズ のフレームワーク設計ガイドラインから直接回答を差し上げます。

からの例外のスローを避けるToString

インスタンスに関連付けられた一意の文字列を返すことを検討してください。

の出力を、ToStringこの型の解析メソッドの有効な入力にすることを検討してください。

ToString目に見える副作用がないことを確認してください。

ToString適切なアクセス許可を要求した後にのみ、オーバーライドを介してセキュリティ機密情報を報告してくださいアクセス許可の要求が失敗した場合は、セキュリティ上の機密情報を除く文字列を返します。

このObject.ToStringメソッドは、一般的な表示およびデバッグの目的で使用することを目的としています。デフォルトの実装では、単にオブジェクト タイプ名が提供されます。デフォルトの実装はあまり役に立ちません。メソッドをオーバーライドすることをお勧めします。

ToString人間が読める興味深い文字列が返される可能性がある場合は常にオーバーライドしてください。デフォルトの実装はあまり役に立たず、カスタム実装はほとんどの場合、より多くの価値を提供できます。

一意ではあるが判読できない ID よりもわかりやすい名前を優先してください

また、Chris SellsToStringがユーザー インターフェイスにとってしばしば危険であるとガイドラインで説明しているので、言及する価値もあります。一般的に、私の経験則では、UI に情報をバインドするために使用されるプロパティを公開し、ToString診断情報を表示するためのオーバーライドを開発者に任せます。お手持ちの型も一緒に飾っていただけますDebuggerDisplayAttribute

返される文字列をToString短く保つようにしてください。デバッガーはToString、開発者に表示されるオブジェクトのテキスト表現を取得するために使用します。文字列がデバッガーで表示できる長さよりも長い場合、デバッグ エクスペリエンスが妨げられます。

カルチャに依存する情報を返すときに、現在のスレッド カルチャに基づくDO文字列の書式設定。

から返される文字列がカルチャに依存する場合、または文字列をフォーマットするさまざまな方法がある場合は、 overloadToString(string format)または implementを提供してください。たとえば、オーバーロードと実装を提供します。IFormattableToStringDateTimeIFormattable

から空の文字列または null を返さないでくださいToString

私はこれらのガイドラインを誓います。この 1 つのガイドラインだけでは、私のコードがどのように改善されたかはわかりませんToStringIEquatable(Of T)や なども同様IComparable(Of T)です。これらのことにより、コードは非常に機能的になり、実装に余分な時間を費やしたことを後悔することはありません.

個人的には、私はユーザー インターフェイスにToString あまり使用したことがなく、常になんらかのプロパティまたはメソッドを公開してきました。ほとんどの時間はToString、デバッグと開発目的に使用する必要があります。重要な診断情報を表示するために使用します。

于 2012-04-23T10:02:07.353 に答える
127
  • オーバーライドする必要がありますToStringか? いいえ。

  • 別の方法でオブジェクトの文字列表現を取得できますか? はい。

しかし、使用することで、すべてのオブジェクトToStringに共通のメソッドを使用しているため、他のクラスはこのメソッドについて知っています。たとえば、.NET フレームワークがオブジェクトを文字列表現に変換する必要がある場合は常に、が最有力候補です (より精巧な書式設定オプションを提供したい場合は、他にもあります)。ToString

具体的には、

Console.WriteLine(yourObject);

を呼び出しyourObject.ToString()ます。

于 2012-04-23T09:40:11.173 に答える
39

オーバーライドToString()を使用すると、人間が判読できる便利なクラスの文字列表現を指定できます。

これは、出力がクラスに関する有用な情報を明らかにできることを意味します。たとえば、Person クラスがある場合ToString()、その人の ID、名、姓などを出力することを選択できます。これは、デバッグまたはロギングの際に非常に役立ちます。

あなたの例に関して-このクラスが何であるかを知らずにオーバーライドが役立つかどうかを判断するのは困難ですが、実装自体は問題ありません。

于 2012-04-23T09:38:51.587 に答える
13

常に適切ですが、表示する内容の背後にある意図を慎重に検討してください

より良い質問は、次のように尋ねることです。

なぜ ToString() をオーバーライドするのでしょうか?

ToString() は、オブジェクトの状態へのウィンドウです。要件として状態を強調します。Java/C# のような強力な OOP 言語は、すべてをクラスにカプセル化することで OOP モデルを悪用します。強力な OOP モデルに従わない言語でコーディングしていると想像してください。クラスと関数のどちらを使用するかを検討してください。これを関数 (つまり、動詞、アクション) として使用し、内部状態が入出力間で一時的に維持されるだけの場合、ToString() は値を追加しません。

他の人が述べたように、デバッガーや他のシステムで使用される可能性があるため、ToString() で出力するものを考慮することが重要です。

私は、ToString メソッドをオブジェクトの --help パラメーターとして想像するのが好きです。短く、読みやすく、明白で、表示しやすいものにする必要があります。オブジェクトが何をするかではなく、オブジェクトが何であるかを表示する必要があります。以上のことを踏まえて考えてみましょう...

使用例 - TCP パケットの解析:

アプリケーション レベルのみのネットワーク キャプチャではなく、pcap キャプチャのようなより機能的なものです。

コンソールにデータを出力できるように、TCP 層だけに ToString() をオーバーロードします。それには何が含まれますか?あなたは気が狂って、すべての TCP 詳細を解析することができます (つまり、TCP は複雑です)...

これには以下が含まれます:

  • ソース ポート
  • 宛先ポート
  • シーケンス番号
  • 承認番号
  • データオフセット
  • フラグ
  • ウィンドウ オフセット
  • チェックサム
  • 緊急ポインター
  • オプション(私そこに行くつもりはありません)

しかし、100 パケットで TCP.ToString() を呼び出していた場合、そのジャンクをすべて受信したいと思いますか? もちろんそうではありません。それは情報過多です。簡単で明白な選択は、最も賢明な選択でもあります...

人々が期待するであろうことを明らかにする:

  • ソース ポート
  • 宛先ポート

私は、人間が解析しやすいがYMMVである賢明な出力を好みます。

TCP:[destination:000, source:000]

複雑なことは何もありません。出力はマシンが解析するためのものではありません (つまり、コードを悪用されている場合を除きます)。本来の目的は、人間が読みやすくすることです。

しかし、前に話したその他の有益な情報についてはどうですか? それも役に立ちませんか? いきますが、まずは…


ToString() は、これまでで最も価値があり、あまり使用されていないメソッドの 1 つです。

理由は 2 つあります。

  1. 人々は ToString() の目的を理解していません
  2. 基本の「オブジェクト」クラスには、同様に重要な別の文字列メソッドがありません。

理由 1 - ToString() の有用性を悪用しないでください。

多くの人が ToString() を使用して、オブジェクトの単純な文字列表現を取得します。C# のマニュアルには、次のように記載されています。

ToString は、.NET Framework の主要な書式設定メソッドです。オブジェクトを表示に適した文字列表現に変換します。

それ以上の処理ではなく、表示します。上記の TCP パケットの素敵な文字列表現を使用して、正規表現 ::cringe:: を使用して送信元ポートを取得するという意味ではありません。

正しい方法は、SourcePort プロパティで直接 ToString() を呼び出すことです (ところで、これは ushort であるため、ToString() は既に使用可能になっているはずです)。

機械解析のために複雑なオブジェクトの状態をパッケージ化するために、より堅牢なものが必要な場合は、構造化されたシリアル化戦略を使用する方がよいでしょう。

幸いなことに、そのような戦略は非常に一般的です。

  • ISerializable (C#)
  • ピクルス (パイソン)
  • JSON (Javascript またはそれを実装する任意の言語)
  • 石鹸
  • 等...

注: PHP を使用していない限り、herp-derp には ::snicker:: 用の関数があります。

理由 2 - ToString() では不十分:

これをコアに実装する言語はまだ見ていませんが、このアプローチのバリエーションを実際に見たり使用したりしています。

その一部は次のとおりです。

  • ToVerboseString()
  • ToString(verbose=true)

基本的に、TCP パケットの状態の毛むくじゃらの混乱は、人間が読みやすいように説明する必要があります。TCP について話すことで「死んだ馬を打ち負かす」ことを避けるために、ToString() と ToVerboseString() が十分に活用されていないと思う 1 番目のケースに「指を向ける」ことにします...

ユースケース - 配列:

主に 1 つの言語を使用する場合は、その言語のアプローチに慣れているでしょう。私のようにさまざまな言語を行き来する人にとって、さまざまなアプローチの数はいらいらする可能性があります。

つまり、これが私を苛立たせた回数は、すべてのヒンズー教の神のすべての指を合わせた合計よりも多い.

言語が一般的なハックを使用するさまざまなケースと、それを正しく行ういくつかのケースあります。車輪の再発明が必要なものもあれば、浅いダンプを行うものもあれば、深いダンプを行うものもあり、どれも私が望むようには機能しません...

私が求めているのは、非常に単純なアプローチです。

print(array.ToString());

出力: 'Array[x]' または 'Array[x][y]'

x は最初の次元のアイテム数、y は 2 番目の次元のアイテム数、または 2 番目の次元がギザギザであることを示す値 (最小/最大範囲でしょうか?) です。

と:

print(array.ToVerboseString());

私はきれいなものが好きなので、she-bang 全体を pretty-print で出力します。

うまくいけば、これは私を長い間悩ませてきたトピックに光を当てます. 少なくとも、PHPers がこの回答に反対票を投じるように、ちょっとしたトロールベイトをまき散らしました。

于 2012-04-27T09:51:39.230 に答える
9

それは何よりも優れた実践に関するものです。

ToString()オブジェクトの文字列表現を返すために多くの場所で使用され、通常は人間が使用します。多くの場合、同じ文字列を使用してオブジェクトを再水和することができますが (intまたはなどDateTimeを考えてください)、それは常に与えられているとは限りません (たとえば、ツリーには、単純に Count を表示する便利な文字列表現があるかもしれませんが、明らかに使用することはできませんそれを再構築すること)。

特に、デバッガーはこれを使用して変数をウォッチ ウィンドウやイミディエイト ウィンドウなどに表示するため、ToString実際にはデバッグに非常に役立ちます。

また、一般に、このような型には、文字列を返す明示的なメンバーも含まれていることがよくあります。たとえば、緯度と経度のペアには、たとえばToDecimalDegreeswhich が返される可能性がありますが、緯度と経度のペアの別の形式であるため、 も含まれる場合があります。その同じタイプは、デバッグなどの「デフォルト」を提供するために、それらのいずれかでオーバーライドすることも、Web ページのレンダリングなどの可能性さえあります (たとえば、Razor の構造は、非文字列式の結果を出力ストリーム)。"-10, 50"ToDegreesMinutesSecondsToString@ToString()

于 2012-04-23T09:42:27.620 に答える
6

object.ToString()オブジェクトをその文字列表現に変換します。作成したクラスをユーザーが呼び出したときに返されるものを変更したい場合は、そのクラスでToString()オーバーライドする必要がありますToString()

于 2012-04-23T09:40:22.477 に答える
6

最も有用な情報はすでに提供されていると思いますが、2 セント追加します。

  • ToString()オーバーライドされることを意図しています。そのデフォルトの実装は型名を返します。これは、(特に多くのオブジェクトを操作する場合に) 役立つ場合もありますが、ほとんどの場合は十分ではありません。

  • デバッグの目的で、信頼できることに注意してDebuggerDisplayAttributeください。詳細については、こちらをご覧ください。

  • 原則として、POCO ではいつでもオーバーライドできますToString()。POCO はデータの構造化された表現であり、通常は文字列になります。

  • オブジェクトのテキスト表現になるように ToString を設計します。おそらく、その主要なフィールドとデータ、コレクション内のアイテム数の説明などです。

  • 常にその文字列を 1 行に収めるようにして、重要な情報だけを記載してください。PersonName、Address、Number などのプロパティを持つクラスがある場合は、メイン データのみを返します (ID 番号に名前を付けます)。

  • の適切な実装をオーバーライドしないように注意してくださいToString()。一部のフレームワーク クラスは既に を実装していますToString()。そのデフォルトの実装をオーバーライドすることは悪いことです。人々は特定の結果を期待し、ToString()別の結果を得るでしょう。

を使用することを本当に恐れないでくださいToString()。私が注意する唯一のことは、機密情報を返すことです。それ以外は、リスクは最小限です。確かに、一部の人が指摘しているように、他のクラスは情報に到達するたびに ToString を使用します。しかし、実際の情報を取得するよりも型名を返す方が良いと考えられるのはどのような場合でしょうか?

于 2012-04-25T22:13:04.573 に答える
5

オーバーライドしないToStringと、基本クラスの実装が取得されます。これObjectは、クラスの短い型名にすぎません。

他のより意味のある、または有用な実装が必要な場合は、ToStringそれをオーバーライドしてください。


が自動的に表示されるため、これは、タイプのリストをデータソースListBoxとして使用する場合に役立ちます。ToString

タイプの表現を取得するためString.Formatに呼び出すタイプを渡したい場合、別の状況が発生します。ToString

于 2012-04-23T09:39:42.270 に答える
4

まだ誰も言及していないこと: をオーバーライドすることで、次のことができるようにToString()実装を検討することもできます。IFormattable

 public override ToString() {
   return string.Format("{0,-20} {1, -20}", m_work, m_personal);
 }

 public ToString(string formatter) {
   string formattedEmail = this.ToString();
   switch (formatter.ToLower()) {
     case "w":
       formattedEmail = m_Work;
       break;
     case "p":
       formattedEmail = m_Personal;
       break;
     case "hw":
       formattedEmail = string.Format("mailto:{0}", m_Work);
       break;
   }
   return formattedEmail;
}

これは便利です。

于 2012-05-04T22:24:49.053 に答える
3

ToString() をオーバーライドする利点の 1 つは、Resharper のツール サポートです: Alt + Ins -> "Formatting members" で、ToString() が自動的に書き込まれます。

于 2012-04-24T21:54:16.853 に答える
2

場合によっては、デバッガーのウォッチ ウィンドウでカスタム クラスの値を読みやすくなります。ウォッチ ウィンドウに表示したい内容が正確にわかっている場合、その情報で ToString をオーバーライドすると、それが表示されます。

于 2012-04-23T15:59:06.233 に答える
1

人のように、文字列表現の直感的でない意味を持つオブジェクトがある場合に使用できます。したがって、たとえばこの人物を印刷する必要がある場合は、このオーバーライドを使用してフォーマットを準備できます。

于 2012-04-25T07:19:42.703 に答える
1

構造体 (実質的にはユーザー プリミティブ) を定義するとき、特に XML シリアライゼーションの場合、一致するToString、 andParseおよびメソッドを使用することをお勧めします。TryParseこの場合、状態全体を文字列に変換して、後で読み取ることができるようにします。

ただし、クラスはより複雑な構造であり、通常は複雑すぎてToStringとを使用できませんParse。それらのToStringメソッドは、状態全体を保存するのではなく、名前や ID などの一意の識別子、またはリストの数量など、状態を識別するのに役立つ簡単な説明にすることができます。

また、Robbie が言ったように、オーバーライドにより、参照を type と同じように基本的ToStringに呼び出すことができます。ToStringobject

于 2012-04-23T15:04:20.947 に答える
0

単純化は、プロパティがどのように使用されるかによって異なります。文字列を 1 回だけフォーマットする必要がある場合は、それをオーバーライドしてもあまり意味がありません。

ただし、 ToString メソッドをオーバーライドして、プロパティの通常の文字列データを返すのではなく、標準の書式設定パターンを実行しているようです。パディング付きのstring.formatを使用しているため。

学んでいるとおっしゃっていたので、カプセル化とコードの再利用に関連するオブジェクト指向プログラミングのコア原則にも触れているようです。

パディング用に設定した引数を取る string.format により、プロパティを呼び出すコードで毎回同じ方法でプロパティがフォーマットされることが保証されます。同様に、今後は、多くの場所ではなく、1 つの場所で変更するだけで済みます。

素晴らしい質問といくつかの素晴らしい答え!

于 2012-04-25T14:49:53.950 に答える
0

エンティティ クラスの ToString メソッドをオーバーライドすると、特にアサーションが失敗したときにテストの問題をすばやく特定するのに役立つため、テスト コンソールがオブジェクトの ToString メソッドを呼び出すと便利です。

しかし、以前に言われたことと一致して、問題のオブジェクトの人間が読める表現を与えることです。

于 2012-04-27T10:05:27.637 に答える