- PR -

Console.WriteLineについて

1
投稿者投稿内容
DaikiRyuto
大ベテラン
会議室デビュー日: 2002/07/23
投稿数: 200
投稿日時: 2002-09-18 12:32
川俣先生の連載を拝見していてふと疑問に思ったことがあります。

http://www.atmarkit.co.jp/fdotnet/csharp_abc2/csabc2_005/cs2_005_01.html

5-2 整数型からメソッドを呼ぶ
にて、
最後に

>> 数値としての値は「123」だが、これを文字列に変換した結果も、123となっている。間違いなく整数型変数に対して、ToString()が機能していることがわかるだろう。

と書かれてありますが、そもそもConsole.WriteLineはint型の引数については内部的にToStringメソッドを呼び出して変換しているのではないかなと思いました。
とすると、List5-1の

>> 12: Console.WriteLine( "i={0}, s={1}", i, s );

iは内部的にToStringメソッドで変換されるから、sと同じ値になるのは当たり前ではないかと考えました(連載の主旨とはずれている疑問ですが)。

それで調べたのですが、int型の引数一つの場合は、ToStringメソッドを呼び出しているようです。
複数の引数で呼び出された場合は
Console.WriteLine(string, object[])
が、適合するようですが、object[]についてToStringメソッドを呼ぶのかどうかについての情報が見つかりませんでした。
多分ToStringメソッドを呼んでいるんだと思いますが、どこかに正確な情報がありましたらご教授ください。
autumn
大ベテラン
会議室デビュー日: 2001/07/27
投稿数: 215
投稿日時: 2002-09-18 13:33
 前半の、最終的に同じ変換機能が動作しているのだから同じ値になるのは当然ではないか?という意見はイエスです。
 後半は、あまりクラスライブラリの深いところは良く分からないのですが。リファレンスのString.Formatメソッドに書いてあるこれではないでしょうか?
引用:

argN が IFormattable を実装している場合は、 argN.Format(formatString, null) によって書式指定が行われます。それ以外の場合は、 argN.ToString() によって書式指定が行われます。 argN が null の場合は、代わりに空文字列が使用されます。 formatString を省略した場合は、 N で指定した引数の ToString() メソッドによって書式指定が行われます。


DaikiRyuto
大ベテラン
会議室デビュー日: 2002/07/23
投稿数: 200
投稿日時: 2002-09-18 14:19
ありがとうございます。

するとやはり
Console.WriteLine( "i={0}, s={1}", i, s );

Console.WriteLine(string, object[]);
で呼ばれ、内部的にToStringメソッドが呼び出されるんですね。

しかし、そうなると、iは、内部的にToStringメソッドで変換される前に、object[]に格納する時点でボクシングされてしまうということでしょうか?

そろそろ逆アセンブルしろと言われそうなので、試してみました。

コード:
int i = 123;
string s = "XXX";
System.Console.WriteLine("i={0} s={1}", i, s);



コード:
int i = 123;
string s = "XXX";
System.Console.WriteLine("i={0} s={1}", i.ToString(), s);



の両者を逆アセンブルして比較してみました。
違いが出た箇所だけ載せてみます。

コード:
  IL_000e:  ldloc.0
  IL_000f:  box        [mscorlib]System.Int32
  IL_0014:  ldloc.1
  IL_0015:  call       void [mscorlib]System.Console::WriteLine(string,
                                                                object,
                                                                object)



コード:
  IL_000e:  ldloca.s   i
  IL_0010:  call       instance string [mscorlib]System.Int32::ToString()
  IL_0015:  ldloc.1
  IL_0016:  call       void [mscorlib]System.Console::WriteLine(string,
                                                                object,
                                                                object)



見てのとおり、ToStringしていない方はボクシングしているようですね。
これは…微妙に速度などに差が?(^_^;
明示的にToStringメソッドを呼んだ方が良かったり(あるいはその逆)するんでしょうか?
autumn
大ベテラン
会議室デビュー日: 2001/07/27
投稿数: 215
投稿日時: 2002-09-19 10:55
引用:

これは…微妙に速度などに差が?(^_^;


 整数をToString()してstring型で渡す場合と、整数をobject型で渡して渡された先でToString()する場合の速度を比較するプログラムをちょこっと作ってみました。
 この結果がどこまで意味があるかは保証できませんが、差はあるようです。

コード:
using System;

namespace ConsoleApplication4
{
    class Class1
    {
        private static void test1( string s )
        {
        }
        private static void test2( object o )
        {
            o.ToString();
        }
        [STAThread]
        static void Main(string[] args)
        {
            const int count = 100000000;
            DateTime start1 = DateTime.Now;
            for( int i=0; i<count; i++ )
            {
                test1(0.ToString());
            }
            DateTime end1 = DateTime.Now;
            Console.WriteLine( end1-start1 );

            DateTime start2 = DateTime.Now;
            for( int i=0; i<count; i++ )
            {
                test2(0);
            }
            DateTime end2 = DateTime.Now;
            Console.WriteLine( end2-start2 );
        }
    }
}



結果(デバッグビルド、Pentium4/1.5GHz):
00:00:57.8749513
00:01:05.7364908
1

スキルアップ/キャリアアップ(JOB@IT)