C# supports two predefined reference types, object and string, described in the following table.
The object Type
Many programming languages and class hierarchies provide a root type, from which all other objects in the hierarchy are derived. C# and .NET are no exception. In C#, the object type is the ultimate parent type from which an other intrinsic and user-defined types are derived. This is a key feature of C# that distinguishes it from both Visual Basic 6.0 and C++, although its behavior here is very similar to Java. All types implicitly derive ultimately from the System.Object class. nus means that you can use the object type for two purposes:
- You can use an object reference to bind to an object of any particular sub type. For example, you will see how you can use the object type to box a value object on the stack to move it to the heap. object references are also useful in reflection, when code must manipulate objects whose specific types are unknown. This is similar to the role played by a void pointer in C++ or by a variant data type in VB.
- The object type implements a number of basic, general ..purpose methods, which include Equals (), GetHashCode(), GetType(), and ToString (). Responsible user-defined classes
may need to provide replacement implementations of some of these methods using an object oriented technique known as overriding, When you override ToString(), for example, you equip your class with a method for intelligently providing a string representation of itself. If you don’t provide your own implementations for these methods in your classes, the compiler will pick up the implementations in object, which mayor may not be correct or sensible in the context of your classes.
We examine tile object type in more detail in subsequent chapters.
The string Type
Veteran! of C and C++ probably have battle scars from wrestling with C-style strings. A C or C++ string is nothing more than an array of characters, so the client programmer has to do a lot of work just to copy one string to another or to concatenate two strings. In fact, for a generation of C++ programmers, implementing a string class that wraps up the.messy details of these operations was a rite of passage requiring many hours of teeth gnashing and head scratching. Visual Basic programmers have a somewhat easier life, with a string type, and Java people have it even better, with a String class that is in many ways very similar to a C# string.
C# recognizes the string keyword, which under the hood is translated to the .NET class, System .String. With it, operations like string concatenation and string copying are a snap:
string str1 = *Hello* ;
string str2 = *World* ;
string str3 = str1 + str2; II string concatenation
Despite this style of assignment, string is a reference type. Behind the scenes, a string object is allocated on the heap, not the stack, and when you assign one string variable to another string, you get two references to the same string in memory. However, with string there are some differences from the usual behavior for reference types. For example, should you make changes to one of these strings, this will create an entirely new string object, leaving the other string unchanged. Consider the following code:
The output from this is:
s1 is a string
s2 is a string
s1 is now another string
s2 is now a string
Changing the value of 51 had no effect on s2, contrary to what you’d expect with a reference type! What’s happening here is that when s1 is initialized with the value a string, a new string object is allocated on the heap. When s2 is initialized, the reference points to this same object, so s2 also has the value a string. However, when you now change the value of s1, instead of replacing the original value, a new object will be allocated on the heap for the new value. The s2 variable will still point to the original object, so its value is unchanged. Under the hood, this happens as a result of operator overloading, a topic that is explored in Chapter 6, “Operators and Casts.” In general, the string class has been implemented so that its semantics follow what you would normally intuitively expect for a string.
String literals are enclosed in double quotation marks (•… ,); if you attempt to enclose a string in single quotation marks, the compiler will take the value as a char, and throw an error. C# strings can contain the same Unicode and hexadecimal escape sequences as chars. Because these escape sequences start with a backslash, you can’t use this character unescaped in a string. Instead, you need to escape it with two backslashes (\ \):
string filepath = ”C:\\proCSharp\\First.cs”;
Even if you are confident that you can remember to do this all the time, typing all of those double hack slashes can prove annoying. Fortunately, C# gives you an alternative. You can prefix a string literal with the at character (@)and all the characters in it will be treated at face value; they won’t be interpreted as escape sequences:
This even allows you to include line breaks in your string literals:
string jabberwocky = @”Twas brillig and the slithy toves Jld gyre and gimble in the wabe.”;
Then the value of jabberwocky would be this:
‘Twas brillig and the slithy toves Did gyre and gimble in the wabe”