Detailed explanation of the difference between StringBuilder and TextWriter in net

  • 2021-11-24 01:15:01
  • OfStack

In my spare time recently, I saw some open source class libraries, and saw that some class libraries like to use TextWriter classes to record related string data. I feel curious about why I don't use StringBuilder class objects. So I searched the Internet once and summarized the relevant notes.

Class StringBuilder

In. net, as a basic data type, string usually maintains only one copy of the same string in one program. That is, a string reference by giving a string value directly will refer to the same data. The advantage of this process is that it can reduce the memory space occupied by strings, and it does not need to open up multiple spaces for multiple identical strings. In C #, the string type is an invariant, and assigning a new value to a string reference does not change the corresponding data in memory, but sets the reference to the new string position.

In normal times, this kind of processing logic can greatly reduce the memory space occupied by strings, but sometimes it will have the opposite effect. The typical example is the intermediate string data generated during the operation of constructing strings. For example:


string[] words = {"Nice ", "to ", "meet ", "you."};
string sentence = "";
for(i = 0;i < words.Length; i++)
{
  sentence += words[i];
}

This is a very simple string assembly function, which splices a given word into a sentence. What we want is to splice it directly into the final result, but this code will generate the previous temporary besides the final sentence. That is, "Nice", "Nice to", "Nice to meet" and the final string "Nice to meet you." will all be constructed with one iteration. But in fact, for us, only the last sentence is needed, and the middle part is not needed at all. Therefore, we need new ways to avoid meaningless expenses.

The StringBuilder class is a way to construct strings dynamically and flexibly. The advantage of this string construction is that it avoids constructing intermediate string results and instead generates the final string data directly. According to the above example, with a little modification, you can get a version with better performance, under which only the last sentence string will be generated.


string[] words = {"Nice ", "to ", "meet ", "you."};
StringBuilder sentenceBuilder = new StringBuilder();
for(i = 0;i < words.Length; i++)
{
  sentenceBuilder.Append(words[i]);
}
string setence = sentenceBuilder.ToString();

As for the principle of StringBuilder class, my personal guess is to maintain an char list in this class, and then dynamically modify the array elements, so that the string will not be generated every time it is spliced, and it will only be generated when the command is explicitly called to generate. However, due to limited capabilities, I still don't know how to find an implementation of StringBuilder in the open source library runtime.

Class TextWriter

TextWriter is an abstract class. According to the description given by Microsoft, this class refers to a writer that can write an ordered character series. Well, I know all the words, but this sentence doesn't feel like a human being. Actually, my personal understanding of this class is that it is a writer. In other words, TextWriter describes a writing process, but what exactly? Write to where? This is not the topic that this abstract class cares about, but the responsibility of its subclasses.

. There are 1 built-in subclasses commonly used in net:

StreamWriter: I believe many people are familiar with this class. When you need to write data to a file, you often write data through this class StringWriter: The object of today's article, writing to a string HttpWriter: Writing data to network flow

StringWriter class is an inherited class of TextWriter. According to MSDN, the explanation given is that TextWriter class object used to write information to string looks similar to StringBuilder class, so why design two different classes in. net to do the same function? After turning over the relevant information, we can only say that these two classes are the products of different design ideas. StringBuilder is a flexible string-building class that does not generate additional temporary strings, whereas StringWriter uses string data as a write destination, which is indeed a necessary implementation from this point of view.

For example, there is a function that specifically logs string data. To be specific, you can imagine that a logger logs log information somewhere. In this case, we provide two input parameters, TextWriter class object indicates a writer, and message describes a log information, so the recorded data only needs to be written like this:


public void WriteData(TextWriter writer, string message)
{
  writer.Write(message);
}

In this way, if you record information in a file, just write this:


using var file = new FileStream("./log.txt", FileAccess.Write);
using var writer = new StreamWriter(file);
WriteData(writer, "hello");

If you want to record information in a variable, this is the case:


var writer = new StringBuilder();
WriteData(writer, "hello");
data = writer.ToString();

Summarize

In general, if you simply use a string without modifying the string value, you can use the string type directly. If the requirement is to focus more on constructing some kind of string data, then using StringBuilder is a better choice. If the requirement emphasizes writing string data in a certain format to a certain medium, it is better to use the inheritance class corresponding to TextWriter, which is more in line with the idea of encapsulation, and does not need to pay too much attention to how the data is written, just pass the data to be written into it.


Related articles: