Are StringBuilder strings immutable? - c#

StringBuilder has a reputation as being a faster string manipulation tool than simply concatenating strings. Whether or not that's true, I'm left wondering about the results of StringBuilder operations and the strings they produce.
A quick jaunt into Reflector shows that StringBuilder.ToString() doesn't always return a copy, sometimes it seems to return an instance of the internal string. It also seems to use some internal functions to manipulate the internal strings.
So what do I get if I do this?
string s = "Yo Ho Ho";
StringBuilder sb = new StringBuilder(s);
string newString = sb.ToString();
sb.Append(" and a bottle of rum.");
string newNewString = sb.ToString();
Are newString and newNewString different string instances or the same? I've tried to figure this out via reflector, and I'm just not quite understanding everything.
How about this code?
StringBuilder sb = new StringBuilder("Foo\n");
StringReader sr = new StringReader(sb.ToString());
string s = sr.ReadLine();
sb.Append("Bar\n");
s = sr.ReadLine();
Will the last statement return null or "Bar"? And if it returns one or ther other, is this defined or undefined behavior? In other words, can I rely on it?
The documentation is remarkably terse on this subject, and I'm reluctant to rely on observed behavior over specification.

Outside of mscorlib, any instance of a System.String is immutable, period.
StringBuilder does some interesting manipulation of Strings internally but at the end of the day it won't return a string to you and then subsequently mutate it in a way that is visible to your code.
As to whether subsequent calls to StringBuilder.ToString() returns the same instance of a String or a different String with the same value, that is implementation dependent and you should not rely on this behavior.

newString and newNewString are different string instances.
Although ToString() returns the current string, it clears its current thread variable. That means next time you append, it will take a copy of the current string before appending.
I'm not entirely sure what you're getting at in your second question, but s will be null: if the final characters in a file are the line termination character(s) for the previous line, the line is not deemed to have an empty line between those characters and the end of the file. The string which has been read previously makes no difference to this.

Are newString and newNewString
different string instances or the
same? I've tried to figure this out
via reflector, and I'm just not quite
understanding everything.
They are different string instances: newString is "Yo Ho Ho" and newNewString is "Yo Ho Ho and a bottle of rum.". strings are immutable, and when you call StringBuilder.ToString() the method returns an immutable string that represents the current state.
Will the last statement return null or
"Bar"? And if it returns one or ther
other, is this defined or undefined
behavior? In other words, can I rely
on it?
It will return null. The StringReader is working on the immutable string you passed to it at the constructor, so it is not affected by whatever you do to the StringBuilder.

The whole purpose of this class is to make string mutable, so it actually is. I believe (but not sure) it'll return the same string that goes into it only if nothing else had been done with this object. So after
String s_old = "Foo";
StringBuilder sb = new StringBuilder(s_old);
String s_new = sb.ToString();
s_old would be the same as s_new but it won't be in any other case.
I should note, that for Java compiler automatically convert multiple string additions into operations with StringBuilder (or StringBuffer which is similar but even faster) class and I would be really surprised in .NET compiler doesn't do this conversion also.

Related

Set specific length for each string

I dont know if there is aleady a fuction which is doing this:
I need to keep specific lenght for my string 20 characters. if my string is 5 characters then to keep rest 15 empty bytes to be null spaces in front of it.
Example
string test=12345;
string finalstring =test;
output
finalstring= 12345;
or
string test=13 characters;
string finalstring = 13 characters;
I cant specify it better.
You can't specify the length of a string in C#. In C# strings are immutable, meaning they can't change once they are initialized and although they are reference type they work much like value types do in a sense that they grow and shrink via formatting etc. In other words, every string instance in C# is the length and final length it will ever be and that can't change. The reference to the string can change, which may be a format of other strings. Take this for example:
var Name = string.empty;
Here Name is an immutable string of 0 characters and is empty.
Name = Name + "Michael";
Here Name combines the immutable empty string with the immutable "Michael" string and reassigns the Name reference to the new value immutable string value of "Michael". So yes, in this instance, there are 3 strings added to the heap now. This is why formatting strings in C# can be very resource intensive.
However; there is a StringBuilder class which handles this work for you. It allows you to pass in strings and or characters and build an array of characters internally, that can be then translated to a string at the end.
var nameBuilder = new StringBuilder();
nameBuilder.Append("Michael");
Now there is only, so far, one immutable string of "Michael" that was used and added to nameBuilder. This in turn can be passed around and manipulated without pushing and popping numerous strings to the heap. This is all a lot but here's you're answer.
In order to specify the length of a string you need to either, work in character arrays or borrow the well adopted StringBuilder. With StringBuilder you can specify the size and max size of the string, work with it in a more string like fashion, and benefit from better use of resources.
var initialCapacity = 20;
var maxCapacity = 20;
var nameBuilder = new StringBuilder(initialCapacity, maxCapacity);
When you're done with StringBuilder you can get the produced string by calling the overridden ToString() method supplied with it.
Hopefully this helps you understand a little bit more about how it works and why you can't set a size for string. Some languages, like C++, have string objects that let you set the max capacity but they are simply an array of characters with built in features. Immutable strings are better for performance but not formatting them in a reasonable way can make them worse; so it's a win / win if you know what you're doing and a lose / lose if you don't.
Use string.PadLeft method. Follow the instructions at msdn
string test="12345";
string finalstring = test.PadLeft(20, ' ');

C# String class: No way of pushing a character to the end of the string?

Really???
I've searched through https://msdn.microsoft.com/en-us/library/system.string(v=vs.110).aspx and don't see any method that can directly push a character onto the end of a string. The best I can figure is
mystr.Insert(mystr.Length, newchar.ToString());
which seems innefficient because of the overhead involved in converting the character to a string and performing string concatenation. My particular use case looks like
while (eqtn[curidx] >= '0' && eqtn[curidx] <= '9') istr.Insert(istr.Length, eqtn[curidx++].ToString());
only because I can't think of a better way to do it. Is there a better way?
Strings in .NET are immutable, so your code doesn't do anything. Every method on a String creates a new instance, it doesn't modify the existing string.
String class overrides + operator to create a new string with the character appended to the end:
istr = istr + eqtn[curidx++];
If you are doing a lot of such operations it will be more efficient to use a StringBuilder. It's basically a mutable String.
You can use the Append method to add a char to end. When you're ready, call ToString to get the constructed string.
Yes, that is absolutely right: you cannot push a character onto the end of a string because C# strings are immutable. Once you have an object, you are stuck with its value until you create a new string object.
On the other hand, creating a new string with an extra character at the end is very simple: use + operator overload that performs concatenation:
string s = "abc";
s += '9'; // s becomes "abc9"
Note that this solution is not so good for use in a loop, because if your loop runs N times you create N throw-away objects in the process. A better solution is to use StringBuilder, which provides a mutable string in C#. StringBuilder class has a convenient Append method, which pushes characters to the end of the StringBuilder. Once you are done building the string, call ToString to harvest the result as an immutable string object.

C# replace string in string

Is it possible to replace a substring in a string without assigning a return value?
I have a string:
string test = "Hello [REPLACE] world";
And I want to replace the substring [REPLACE] with something else:
test = test.replace("[REPLACE]", "test");
This works fine, but how can I do it without assigning the return value to a variable?
I want something like this:
test.replace("[REPLACE]", "test");
As mentioned by dlev, you can't do this with string as strings are immutable in .NET - once a string has been constructed, there's nothing you can do (excluding unsafe code or reflection) to change the contents. This makes strings generally easier to work with, as you don't need to worry about defensive copying, they're naturally thread-safe etc.
Its mutable cousin, however, is StringBuilder - which has a Replace method to perform an in-object replacement. For example:
string x = "Hello [first] [second] world";
StringBuilder builder = new StringBuilder(x);
builder.Replace("[first]", "1st");
builder.Replace("[second]", "2nd");
string y = builder.ToString(); // Value of y is "Hello 1st 2nd world"
You can't, because string is immutable. It was designed so that any "changes" to a string would actually result in the creation of a new string object. As such, if you don't assign the return value (which is the "updated" string, actually copy of the original string with applied changes), you have effectively discarded the changes you wanted to make.
If you wanted to make in-place changes, you could in theory work directly with a char[] (array of characters), but that is dangerous, and should be avoided.
Another option (as pointed out by Mr. Skeet below) is to use StringBuilder and its Replace() method. That being said, simple replacements like the one you've shown are quite fast, so you may not want to bother with a StringBuilder unless you'll be doing so quite often.
Strings in .NET are immutable. They cannot be edited in-line.
The closest you can get to in-line editing is to create a StringBuilder from a string. In-line fiddles with its contents and then get it to spit a string back out again.
But this will still produce a new string rather than altering the original. It is a useful technique, though, to avoid generating lots of intermediary strings when doing lots of string fiddling, e.g. in a loop.
You can't. You have to assign the value, as strings are immutable.
Built-in reference types (C# reference)
You can't. Strings are immutable in .NET.
You can't, as in C# strings are immutable. Something like this would violate that.
You need to have the return type of string, because the one you're working with cannot change.
Here is the code to fetch a string from HTML content and pass it to StringBuilder and set the value from your variable. You cannot do string.replace. You have to use StringBuilder while manipulating. Here in the HTML page I added [Name] which is replaced by Name from code behind. Make sure [Name] is unique or you can give any unique name.
string Name = txtname.Text;
string contents = File.ReadAllText(Server.MapPath("~/Admin/invoice.html"));
StringBuilder builder = new StringBuilder(contents);
builder.Replace("[Name]", Name);
StringReader sr = new StringReader(builder.ToString());

How can I substitute characters in C#

I have strings like this:
var abc = "text1 text2 text3";
I want to change "text3" to "textabc" in the string. Is there a way that I can do this without creating a new string?
Strings are immutable in C# so any operation inherently creates a new string...
From MSDN
Strings are immutable--the contents of
a string object cannot be changed
after the object is created, although
the syntax makes it appear as if you
can do this.
StringBuilders are often the most efficient way to perform manipulation on a "string" due to this fact. Especially if you are concatenating one char at a time for example.
See the StringBuilder.Replace() method - This does not require you reassign the result to another StringBuilder as it actually changes the StringBuilder itself.
Have a look at this article by the very famous Jon Skeet (you'll get to recongise him:)) all about using StringBuilder sensibly.
No, because strings are immutable, but you can reassign the new string to the same variable
var abc = "text1 text2 text3"
abc = abc.Replace("text3", "textabc");
string newString = abc.Replace("text3", "textabc");
Strings are immutables in the CLR : you can never ever change them.
The main question is what do you mean by writing "without creating a new string".
As stated, strings are immutable in .NET, that is, once they're created, they can't change.
However, you can replace them with a new string instance:
var abc = "text1 text2 text3";
abc = abc.Replace("text3", "textabc");
If you want more flexibility, you may want to use StringBuilder, in which you can remove and replace strings as much as you want, and finally use its ToString method to have the result as a string instance.

string manipulations

I have string variable declared globally.I have to append a substring to this string dynamically based on the user input.To do this I use str=str+substring;
In this case the string in str doesn't have meaningful sentence finally ie.,there is no spaces between the words.to make it sense I used the following statement instead,
str=str+" "+substring; or str=str+substring+" ";
here everytime I have to append extra space to the substring before appending this to the main string were additional string processing is required.
Can anybody help on this were i can do this effectively?
It depends on how often you are doing it. If this is intermittent (or in fact pretty-much anything except a tight loop), then forget it; what you have is fine. Sure an extra string is generated occasionally (the combined substring/space), but it will be collected at generation 0; very cheap.
If you are doing this aggressively (in a loop etc), then use a StringBuilder instead:
// declaration
StringBuilder sb = new StringBuilder();
...
// composition
sb.Append(' ').Append(substring);
...
// obtaining the string
string s = sb.ToString();
A final (unrelated) point - re "globally" - if you mean static, you might want to synchronize access if you have multiple threads.
What do you want to achieve exactly? You could store the words in a list
List<string> words = new List<string>();
...
words.Add(str);
And then delay the string manipulation (i.e. adding the spaces between words) until at the very end. This way, you're on the fly operation is just an add to a list, and you can do all the complex processing (whatever it may be) at the end.
If you are doing it rarely, you could slightly pretty up the code by doing:
str += " " + substring;
Otherwise, I'd go with Nanda's solution.
#Nanda: in your case you should use string builder.
StringBuilder data = new StringBuilder();
data.AppendFormat(" {0}", substring);

Categories

Resources