[英]Is there any penalty between appending string vs char in C#
幾年前在Java開發時,我了解到如果我有一個字符而不是帶有一個字符的字符串,最好附加一個字符,因為VM不必對其內部字符串中的字符串值進行任何查找池。
string stringappend = "Hello " + name + ".";
string charappend = "Hello " + name + '.'; // better?
當我開始使用C#進行編程時,我從未想過它與“VM”相同的可能性。 我遇到了C#String Theory-String實習池 ,它說C#也有一個內部字符串池(我想如果不這樣會很奇怪)所以我的問題是,
當連接到關於C#的字符串或者它只是亂碼時,在附加char而不是字符串實際上有什么好處?
編輯:請忽略StringBuilder和string.Format,我更感興趣的是為什么我會替換“。” 用'。' 在代碼中。 我很清楚這些類和功能。
如果給出了選擇,我會在調用System.String.Concat
或(等效的) +
運算符時傳遞string
而不是char
。
我在System.String.Concat
看到的唯一重載都是字符串或對象。 由於char不是字符串,因此將選擇對象版本。 這會導致char被裝箱。 在Concat驗證對象引用不為null之后,它將在char上調用object.ToString。 然后,在創建新的連續字符串之前,它將首先生成可怕的單字符字符串。
所以我不知道如何通過一個炭將獲得任何收益。
也許有人想看看Reflector中的Concat操作,看看是否有特殊的char處理?
UPDATE
正如我所想,這個測試證實了char略慢。
using System;
using System.Diagnostics;
namespace ConsoleApplication19
{
class Program
{
static void Main(string[] args)
{
TimeSpan throwAwayString = StringTest(100);
TimeSpan throwAwayChar = CharTest(100);
TimeSpan realStringTime = StringTest(10000000);
TimeSpan realCharTime = CharTest(10000000);
Console.WriteLine("string time: {0}", realStringTime);
Console.WriteLine("char time: {0}", realCharTime);
Console.ReadLine();
}
private static TimeSpan StringTest(int attemptCount)
{
Stopwatch sw = new Stopwatch();
string concatResult = string.Empty;
sw.Start();
for (int counter = 0; counter < attemptCount; counter++)
concatResult = counter.ToString() + ".";
sw.Stop();
return sw.Elapsed;
}
private static TimeSpan CharTest(int attemptCount)
{
Stopwatch sw = new Stopwatch();
string concatResult = string.Empty;
sw.Start();
for (int counter = 0; counter < attemptCount; counter++)
concatResult = counter.ToString() + '.';
sw.Stop();
return sw.Elapsed;
}
}
}
結果:
string time: 00:00:02.1878399
char time: 00:00:02.6671247
幾年前在Java開發時,我了解到如果我有一個字符而不是帶有一個字符的字符串,最好附加一個字符,因為VM不必對其內部字符串中的字符串值進行任何查找池。
追加一個char
的String
可能會比追加1個字符稍快String
,因為:
append(char)
操作不必加載字符串length
, characters
數組的引用, start
偏移量, 查看String
和相關類的Java源代碼。 你可能會對引擎蓋下的內容感到驚訝。
實習池與它無關。 在類加載期間,字符串文字的實習僅發生一次 。 僅當應用程序顯式調用String.intern()
時,才會發生非文字字符串的實習。
這可能很有趣: http : //www.codeproject.com/KB/cs/StringBuilder_vs_String.aspx
Stringbuilder不一定比Strings快,它如前所述, 取決於它 。 這取決於機器配置,可用內存與處理器功率,框架版本和機器配置。 在這種情況下,你的探查器是你最好的伙伴:)
返回2主題:你應該嘗試更快。 做多次連接並讓你的探查器觀看。 你會看到可能的差異。
.NET中的所有字符串連接(使用標准運算符即+)要求運行時為完整的新字符串保留足夠的內存以保存連接的結果。 這是由於字符串類型是不可變的。
如果您多次執行字符串連接(即在循環內等),您將遇到性能問題(如果字符串足夠大,最終會出現內存問題),因為.NET運行時需要不斷分配和釋放內存空間來保存每個字符串。新字符串。
可能是因為這個原因你(正確地)認為過多的字符串連接可能會有問題。 它與連接char而不是字符串類型的連接很少(如果有的話)。
替代方法是在System.Text命名空間中使用StringBuilder類。 此類表示一個可變的類似字符串的對象,可用於連接字符串而不會產生很多性能問題。 這是因為StringBuilder
類將為字符串保留特定數量的內存,並允許將連接附加到保留內存量的末尾,而不需要整個字符串的完整新副本。
編輯:
關於字符串查找和字符查找的細節,我掀起了這個小測試:
class Program
{
static void Main(string[] args)
{
string stringtotal = "";
string chartotal = "";
Stopwatch stringconcat = new Stopwatch();
Stopwatch charconcat = new Stopwatch();
stringconcat.Start();
for (int i = 0; i < 100000; i++)
{
stringtotal += ".";
}
stringconcat.Stop();
charconcat.Start();
for (int i = 0; i < 100000; i++)
{
chartotal += '.';
}
charconcat.Stop();
Console.WriteLine("String: " + stringconcat.Elapsed.ToString());
Console.WriteLine("Char : " + charconcat.Elapsed.ToString());
Console.ReadLine();
}
}
它只是次數(使用高性能StopWatch類)連接類型字符串的100000個點/句點( .
)與char類型的100000個點/句點所需的時間。 我運行了幾次這個測試,以防止結果偏離一個特定的運行,但是,每次結果類似如下:
String: 00:00:06.4606331
Char : 00:00:06.4528073
因此,在多個連接的背景下,我會說在兩者之間存在很小的差異(很可能,在考慮標准測試運行容差時沒有區別)!
我同意大家對使用StringBuilder的看法,如果你正在進行大量的字符串連接,因為String是一個不可變的類型,但是不要忘記創建StringBuilder類的開銷也是如此,所以你必須選擇何時進行用哪個。
在比爾瓦格納的一本效果C#書中(或者可能是其中的三本書......),他也談到了這一點。 從廣義上講,如果只需要將幾個字符串片段組合在一起,則string.Format更好,但如果需要在可能較大的循環中構建大字符串值,請使用StringBuilder。
每次使用+運算符連接字符串時,運行時都會創建一個新字符串,為了避免這種情況,建議的做法是使用具有Append方法的StringBuilder類。 您還可以使用AppendLine和AppendFormat。 如果您不想使用StringBuilder,那么您可以使用string.Format:
string str = string.Format("Hello {0}.", name);
由於字符串是不可變類型,因此在將值返回給您之前,都需要創建字符串的新實例。
我會考慮使用string.Concat(...)
進行少量連接,或者將StringBuilder
類用於許多字符串連接。
我不能說C#,但在Java中,主要優點不是編譯時增益而是運行時增益。
是的,如果使用String,那么在編譯時,Java必須在其內部池中查找String並可能創建一個新的String對象。 但是這只會在編譯時發生一次,當你創建.class文件時。 用戶永遠不會看到這個。
用戶將看到的是,在運行時,如果你給一個角色,程序只需要檢索角色。 完成。 如果給出一個String,它必須首先檢索String對象句柄。 然后它必須設置一個循環來遍歷所有字符,檢索一個字符,觀察不再有字符,然后停止。 我沒有看過生成的字節碼,但它顯然是多次工作的時間。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.