Last Updated:

String class in .net framework

String class encapsulates a string of Unicode characters as a managed object. The String class is defined in the System namespace and is a standard part of the .NET Framework. The String type is a sealed class; this means that it cannot be the base for another class. The String class itself derives from the System::Object class, which is the basis of the .NET class hierarchy. A String object is immutable, i.e. once initialized, it cannot be changed. The String class contains methods that you can use to modify a String object, such as InsertReplace, and PadLeft.

However, in reality, these methods never change the original object. Instead, they return a new String object that contains the changed text. If you want to be able to modify the source data, you should pay attention to the StringBuilder class, not the String class itself. The following code snippet shows that the Replace method does not affect the contents of the original String object, but does change the contents of the StringBuilder object:

//StringReplace.cpp
#using <mscorlib.dll>
using namespace System; // for console and strings
// use namespace System;
using namespace System::Text; // for StringBuilder
// use namespace System::Text;
void main(void) {
Console::WriteLine("String is immutable:");
// ("The string is immutable: ");
String *psl = S"Hello World"; // String "Hello World"
String *ps2 = psl › Replace('H', 'J'); // Replacement
Console::WriteLine(psl);
Console::WriteLine(ps2);
Console::WriteLine("StringBuilder can be modified:");
// ("StringBuilder can change: ");
StringBuilder *psbl = new StringBuilder(S"Hello World"); // Hello World
StringBuilder *psb2 = psbl › Replace('H', 'J'); // Replacement
Console::WriteLine(psb1);
Console::WriteLine(psb2);
}

The information displayed by the program indicates that it is true that the contents of the object pointed to by psl do not change, i.e. the Replace method does not change the original String object. On the other hand, the *psbl object is modified by the Replace method.

String is immutable:
Hello World
Jello World
StringBuilder can be modified:
Jello World
Jello World

The translation is as follows [Added by the editor of the Russian translation. – Editor's note]:

The string is immutable:
Hello World
Jello World
StringBuilder may change:
Jello World
Jello World

In the code snippet above, you may notice string literals defined with or without the S prefix. A string literal defined using quotation marks only is a pointer to char, which is a pointer to a sequence of ASCII characters that ends in zero. This pointer is not a pointer to a String object. And the string literal defined with the prefix S is a pointer to a managed String object. The prefix L, which was not used in the previous example, indicates a String of Unicode characters, which is also not a String object. The following snippet demonstrates these three types of strings:

char *psl = "ASCII string literal"; // unmanaged
// character *psl = "ASCII string literal";
_wchar_t *ps2 = L"Unicode string literal"; // unmanaged
// L "unicode string literal";
String *ps3 = S"String object literal"; // managed
// String *ps3 = S " string literal - String object ";

The String class contains many useful methods. For example, you can use the Equals method to compare objects, as demonstrated in the following example. For more information about the methods of the String object, see the .NET SDK documentation.

//Strings.cpp
fusing <mscorlib.dll>
using namespace System;
// use namespace System;
void main(void) {
String *pstr1 = new String("hello");
// String *pstr1 = new String ("hello");
String *pstr2 = new String("hello");
// String *pstr2 = new String ("hello");
if (pstrl › Equals(pstr2))
// if (pstrl › Equals (pstr2))
Console::WriteLine("equal"); // equal - executed else
Console::WriteLine("not equal"); // not equal - not
// executed if (pstrl==pstr2) // if (pstrl == pstr2)
Console::WriteLine("equal"); // equal - not executed else
Console::WriteLine("not equal"); // not equal - executed }

The result of the program shows the difference between comparing String objects using the Equals method and the == operator. The Equals method checks the equality of the contents of objects, whereas the == operator checks only the equality of pointers (i.e., the equality of the addresses of objects in memory).

Equal
not equal

Here is the translation [Added by the Editor of the Russian translation. – Editor's note]:

equal
not equal

The ToString method provides a representation of a String object for any managed data type. Although the ToString method is not automatically accessible to unmanaged classes, it is available for packaged meaningful and packaged primitive types, such as int or float (floating-point). Packaging and unpacking, as well as meaningful types, managed and unmanaged types, will be discussed later in this chapter.

The ToString method is most commonly used for output and debugging, and the managed classes that you create typically replace ToString so that it returns developer-defined, readable information about the object. The Object::ToString method simply returns the fully qualified class name of a given object, and its implementation (which is not particularly useful, however) is available through inheritance to any managed type. The following example demonstrates some aspects of how the ToString method works:

//ToString.cpp
#using <mscorlib.dll>
using namespace System;
// use namespace System;
_gc class ClassWithToString
// garbage collector class ClassWithToString
{
public:
String *ToString() // cancel {
return new String("SomeClass - override");
// return a new String ("SomeClass - cancel");
}
};
_gc class ClassNoToString
// garbage collector class ClassNoToString
{
//ToString inherited, no cancellation
};
void main(void)
{
int i = 3;
Console::WriteLine(i.ToString()); // String* overload
Console::WriteLine(i); // int overload
ClassWithToString *psc = new ClassWithToString;
Console::WriteLine(psc › ToString()); // String* overload
Console::WriteLine(psc); // Object* overload
ClassNoToString *psoc = new ClassNoToString;
Console::WriteLine(psoc › ToString()); // String* overload
Console::WriteLine(psoc); // Object* overload
int array _gc[]= new int _gc[5]; // garbage collector array
Console::WriteLine(array › ToString()); // String overload
// (Line)
Console::WriteLine(array); // Object* overload
}

The result of the program is shown below. Note that the ToString method can be called explicitly as an argument to the overloaded WriteLine method of the String object, or you can call the overloaded WriteLine method of the String object, which itself will call the ToString method. Note also that even a managed array (which is actually a managed type) supports the ToString method.

3
3
SomeClass – override SomeClass – override ClassNoToString
ClassNoToString System.Int32[] System.Int32[]

All identical string literals of type String are automatically represented by pointers to objects that are instances of the same String class. This is true for objects represented by string literals of type string, such objects are specified using a quoted string. However, this is not true for String objects that are explicitly created using the new operator. The following example confirms this. It compares two pointers to a String object created using the new operator.

The results displayed to the console confirm that two identical string objects, defined as quoted identical sequences of characters, are the same object (the expression pstr1==pstr2 is true for String objects). On the other hand, two identical string objects created with the new operator are actually different objects (the expression pstrl==pstr2 is false).

//StringLiteral.cpp
#using <mscorlib.dll>
using namespace System;
// use namespace System;
void main(void) {
String *pstrl; // Line
String *pstr2; // Line
// comparison of objects - string literals of type String
pstr1 = S"hello"; // Hey
pstr2 = S"hello"; // Hey
if (pstrl › Equals(pstr2)) // if (pstrl › Equals (pstr2))
Console::WriteLine("equal"); // equal - done else
Console::WriteLine("not equal"); // not equal - failed
 if (pstrl==pstr2) // if (pstrl == pstr2)
Console::WriteLine("equal"); // equal - done else
Console::WriteLine("not equal"); // not equal - failed
// compare new String objects (not literals)
pstr1 = new String("hello"); // pstr1 = new String ("hello");
pstr2 = new String("hello"); // pstr2 = new String ("hello");
if (pstrl › Equals(pstr2)) // if (pstrl › Equals (pstr2))
Console::WriteLine("equal"); // equal - done else
Console::WriteLine("not equal"); // not equal - failed
if (pstrl==pstr2) // if (pstrl == pstr2)
Console::WriteLine("equal"); // equal - failed else
Console::WriteLine("not equal"); // not equal - done }

The program will print:

equal equal equal not equal
equal
equal
equal
not equal

You can use managed String literals string and unmanaged ASCII and Unicode string literals (through automatic wrapping) in expressions that expect to use the managed String object. However, a managed String object cannot be used where variables of unmanaged types are expected to appear. The following example proves it. Notice the commented lines. If not commented out, they would result in a compilation error message.

//MixingStringTypes.cpp
fusing <rascorlib.dll>
using namespace System;
// use namespace System;
tinclude <wchar.h> // for wchar_t
void ExpectingManagedString(String *str){} // String *str void ExpectingASCII
String(char *str){} // character *str void ExpectingUnicode
String(wchar_t *str){} void main(void) {
// expected managed type
ExpectingManagedString(S"hello"); // full match
// hello ExpectingManagedString("hello"); // no error
// Hey
ExpectingManagedString(L"hello"); // no error
// Hey
// expected unmanaged type
ExpectingASCIIString("hello"); // full match
// hello //ExpectingASCIIString(S"hello"); // error!
// hello ExpectingUnicodeString(L"hello"); // full match
// hello //ExpectingUnicodeString(S"hello"); // error!
// Hey }