簡體   English   中英

在C#中追加字符串與char之間是否有任何懲罰

[英]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不必對其內部字符串中的字符串值進行任何查找池。

追加一個charString可能會比追加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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM