2010-05-09 48 views
17

我正在使用Reflector來查看String.Format的實現,並且一直有一個印象,那就是String.Format的重載需要使用一個對象數組的方法的優化版本。但是,我發現它在內部創建一個對象數組,然後調用一個接受對象數組的方法。爲什麼String.Format的重載存在?

1 ARG

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

2 ARGS

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 ARGS

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版本所做的,所以他們看起來多餘。 BCL設計師爲什麼添加這些重載?

回答

7

正如漢斯所言,一個原因是在格式化字符串的大多數常見情況下創建數組是很多不必要的開銷。這節省了EXE中的空間。

另一個原因是並非所有語言都支持可變參數函數(在C#中使用params)。這允許這些語言的用戶避免在最常見的字符串格式化情況下創建數組。這對於那些沒有簡單語法的數組創建和初始化的語言來說可以節省很多。

+0

好點!這對他們的存在非常有意義。 – GiddyUpHorsey 2010-05-09 05:58:27

+0

「創建數組有很多不必要的開銷」數組是在方法內部創建的,在「開銷」方面有什麼不同? – 2015-02-26 18:57:11

+1

@ChrisMarisic:創建數組不是內存使用或GC開銷問題;這是額外的操作碼。僅用一個字符串替換來調用'string.Format'只需要3個IL操作碼,而如果過載不存在則需要10個操作碼。每個附加參數如果可以使用過載,則只需要多一個操作碼,如果使用數組,則需要多於4個操作碼。由於如果方法太多,操作碼不能內聯,這會產生重大影響。 – Gabe 2015-02-26 21:27:38

3

您忘記了撥打電話所需的應用程序代碼。創建數組並填充它比傳遞3個參數需要更多的IL。

+0

你是對的。我不會考慮這個。我想你可以說這些方法優化了調用代碼的大小,而不是我一直認爲它們在那裏的性能。 – GiddyUpHorsey 2010-05-09 06:48:19

+0

那麼,如果你直接在IL中調用它,重載是否有意義? – 2015-02-26 18:58:26

相關問題