18

私はReflectorを使用してString.Formatの実装を調べていましたが、1、2、3個の引数をとるString.Formatのオーバーロードは、オブジェクト配列をとるメソッドの最適化されたバージョンであるという印象を常に受け​​ていました。しかし、私が見つけたのは、内部的にオブジェクト配列を作成してから、オブジェクト配列を受け取るメソッドを呼び出すことでした。

1引数

public static string Format(string format, object arg0)
{
    if (format == null)
    {
        throw new ArgumentNullException("format");
    }
    return Format(null, format, new object[] { arg0 });
}

2つの引数

public static string Format(string format, object arg0, object arg1)
{
    if (format == null)
    {
        throw new ArgumentNullException("format");
    }
    return Format(null, format, new object[] { arg0, arg1 });
}

3つの引数

public static string Format(string format, object arg0, object arg1, object arg2)
{
    if (format == null)
    {
        throw new ArgumentNullException("format");
    }
    return Format(null, format, new object[] { arg0, arg1, arg2 });
}

オブジェクト配列

public static string Format(string format, params object[] args)
{
    if ((format == null) || (args == null))
    {
        throw new ArgumentNullException((format == null) ? "format" : "args");
    }
    return Format(null, format, args);
}

内部的には、それらはすべて同じコードを使用することになります。したがって、1、2、および3引数バージョンを使用することは、オブジェクト配列バージョンよりも高速ではありません。

だから私の質問は-なぜそれらが存在するのですか?

値のコンマ区切りリストでオブジェクト配列バージョンを使用する場合、コンパイラは、params / ParamArrayキーワードが基本的に1、2、および3バージョンと同じであるため、引数をオブジェクト配列に自動的に変換するため、冗長に見えます。BCL設計者がこれらのオーバーロードを追加したのはなぜですか?

4

2 に答える 2

8

ハンスが述べているように、1つの理由は、文字列をフォーマットする最も一般的なケースでは、配列の作成が多くの不要なオーバーヘッドであるということです。これにより、EXEのスペースが節約されます。

もう1つの理由は、すべての言語が可変個引数関数(paramsC#での使用)をサポートしているわけではないことです。これにより、これらの言語のユーザーは、文字列フォーマットの最も一般的なケースで配列の作成を回避できます。これにより、配列の作成と初期化のための単純な構文を持たない言語の多くを節約できます。

于 2010-05-09T05:53:40.550 に答える
3

電話をかけるために必要なアプリのコードを忘れています。配列を作成してそれを埋めるには、3つの引数を渡すよりもはるかに多くのILが必要です。

于 2010-05-09T05:50:22.523 に答える