web-dev-qa-db-ja.com

Console.Writelineの基本

次のコードについて質問があります。

class CurrentDate
    {
        static void Main()
        {
            Console.WriteLine(DateTime.Now);
        }
    }

ドキュメントによると:

指定されたフォーマット情報を使用して、指定されたオブジェクトの配列のテキスト表現と、それに続く現在の行末記号を標準出力ストリームに書き込みます。

だから私の質問は:どうしてWriteLineDateTimeオブジェクトのテキスト表現を知っているのですか?つまり、自分のクラスから自分のオブジェクトを作成した場合、値をテキストに変換する方法をどのように知ることができるでしょうか。さらに、値が何であるかをどのように知るのでしょうか?オブジェクトの「値」をどのように定義できますか?

18
CuriousGuy

WriteLineがDateTimeオブジェクトのテキスト表現を認識するのはなぜですか?つまり、自分のクラスから自分のオブジェクトを作成した場合、値をテキストに変換する方法をどのように知ることができるでしょうか。

_Console.WriteLine_には オーバーロードのセット 特定のタイプ(主にプリミティブ)に一致します。コンパイラーがオーバーロードを指定されたタイプと一致させない場合、_System.Object_(単一のパラメーターを指定することを許可)をとるオーバーロードと一致します。その場合、型がIFormattableを実装しているかどうかを確認し、実装している場合は IFormattable.ToString(null, Formatter) を呼び出します。そうでない場合は、オブジェクトでToStringを呼び出します。 ToStringは、すべてのオブジェクトが継承する_System.Object_で定義されています。カスタム表現が必要なすべてのオブジェクトは、DateTimeのように、デフォルトの動作をオーバーライドします。

たとえば、Foo文字列プロパティを持つBarクラスがあり、Fooを渡すときに意味のあるものを_Console.WriteLine_に出力させたいとします。

_public class Foo
{
    public string Bar { get; set; }
    public override string ToString()
    {
         return Bar;
    }
}
_

そして今、私たちはそれを渡したいと思います_Console.WriteLine_:

_public static void Main(string[] args)
{
      var foo = new Foo { Bar = "bar" };
      Console.WriteLine(foo);
}
_

「バー」を生成します。

17
Yuval Itzchakov

あなたの場合のように、Console.WriteLine(DateTime)にはオーバーロードがないので、Console.WriteLine(Object)オーバーロードが呼び出され、 このオーバーロードはTextWriter.WriteLine(object)overload これは として実装

_IFormattable f = value as IFormattable;
if (f != null)
    WriteLine(f.ToString(null, FormatProvider));
else
    WriteLine(value.ToString());
_

ご覧のとおり、このメソッドは、このオブジェクトタイプが IFormattable interface を実装しているかどうかをチェックします。 Datetimeはこのインターフェースを実装します なので、f.ToString(null, FormatProvider)が呼び出されます。このメソッドの ドキュメント から最初のパラメータは次のとおりです。

IFormattable実装のタイプに対して定義されたデフォルトの形式を使用するためのnull参照(Visual BasicではNothing)。

そして DateTime.ToString(String, IFormatProvider) メソッドのドキュメントから:

Formatがnullまたは空の文字列( "")の場合、標準のフォーマット指定子 _"G"_ 。が使用されます。

つまり、表現は ShortDatePatternLongTimePattern プロパティの組み合わせになります CurrentCulture

カスタムクラスに特別な形式が必要な場合は、タイプの .ToString()メソッドをオーバーライド で動作を変更できます。

9
Soner Gönül

一部の人の考えに反して、DateTime.ToString()は呼び出されません。 .NETでは、オブジェクトはそれ自体を「文字列化」する2つの方法があります。string Object.ToString()メソッドをオーバーライドする方法と IFormattable インターフェイスを実装する方法です。 DateTimeは両方を行います。

今...やってみると

_Console.WriteLine(DateTime.Now);
_

void public static void WriteLine(Object value) オーバーロードが選択されています(VisualStudioでCtrlキーを押しながらWriteLineをクリックすると表示されます)。このメソッドは、単に TextWriter.WriteLine(value) メソッドを呼び出します。

_IFormattable f = value as IFormattable;
if (f != null)
    WriteLine(f.ToString(null, FormatProvider));
else
    WriteLine(value.ToString());
_

これらはすべて、ILSpyを使用して_Console.WriteLine_を探すことで簡単に確認できます。

7
xanatos