[C# Study Notes] Reference Type (2)

Insert image description here


Object

Supports all classes in the .NET class hierarchy and provides low-level services to derived classes. This is the ultimate base class for all .NET classes; it is the root of the type hierarchy.

Simply put, it is universal, it is the parent class of all types. Because all classes in .NET derive from Object, every method defined in the Object class is available to all objects in the system.

Four commonly used methods are provided in the Object class, namely the Equals, GetHashCode, GetType and ToString methods.

Equals

int a = 1;
int b = 1;
if (a.Equals(b))
{
    
    
  Debug.Log("111"); -- 输出111
}

Person a = new Person();
Person b = 1;
if (a.Equals(b))
{
    
    
  Debug.Log("111"); -- 输出111
}

Equals is an equality judgment, which is the same as ==. For value types, it judges whether the values ​​are the same, and for reference types, it judges whether the references are the same.

GetType

Used to obtain the type of the current instance, and the return value is System.Type. The GetType method does not contain any parameters and is a non-static method.

Use Object.GetType() to return the type of the object. The difference between x.GetType() and typeof() is that GetType() is a method of object and can be used for all variables to obtain their types. And typeof(xxx) can only put types inside but not variable names.

ToString

Converts an object to its string representation so it is suitable for display.

The above three methods can be overloaded and rewritten.

GetHashCode

Returns the hash value of the object. The hash value of each object is fixed. This method does not take any parameters and is not a static method, so an instance is required to call the method. Since this method is defined in the Object class, any object can call this method directly.


string

The string type stringrepresents a sequence of zero or more Unicode characters. What's special is that although string is a reference type, ==when used for comparison, it is a value type comparison. It should be noted that string is an immutable type, which means that every time we modify the string string, we actually create a new string.

verbatim text

Use @keywords to identify the string as verbatim text, escape characters will not be recognized

@"""Ahoy!"" cried the captain." // "Ahoy!" cried the captain.
@"c:\Docs\Source\a.txt"  // rather than "c:\\Docs\\Source\\a.txt"

compound format string

Use the String.Format method to combine the variables into the format item, where the number in the brackets represents the corresponding variable index, and the :following represents the specified type of the variable.

String.Format("Name = {0}, hours = {1:hh}", name, DateTime.Now);

Multiple identical indexes can also exist at the same time

string multiple = String.Format("0x{0:X} {0:E} {0:N}",
                                Int64.MaxValue);
Console.WriteLine(multiple);
// The example displays the following output:
//      0x7FFFFFFFFFFFFFFF 9.223372E+018 9,223,372,036,854,775,807.00

String interpolation

Using $keywords to identify string interpolation

string name = "Mark";
var date = DateTime.Now;
// Composite formatting:
Console.WriteLine("Hello, {0}! Today is {1}, it's {2:HH:mm} now.", name, date.DayOfWeek, date);
// String interpolation:
Console.WriteLine($"Hello, {
      
      name}! Today is {
      
      date.DayOfWeek}, it's {
      
      date:HH:mm} now.");

(For more usage, please read the official documentation , especially the methods of the string class. The embarrassing thing is that the string class has so many methods, but String is mostly used by StringBuilder)


StringBuilder

Use the namespace System.Text to introduce the type

StringBuilder can be said to be a completely superior replacement for String, which is a mutable string class. Mutability means that once an instance of a class is created, it can be modified by appending, deleting, replacing, or inserting characters. Since String needs to generate a new string every time it is modified, this also leads to some memory consumption issues that may occur when operating on it. So for strings that need to be manipulated, we would choose StringBuilder, but performance depends on the size of the string, the amount of memory to be allocated for the new string, the system executing the code, and the type of operation.

Consider using the String class in the following situations:

  • When the code makes a small number of changes to the string. In these cases, StringBuilder may provide negligible performance improvements, so String can be used directly.
  • When performing a fixed number of concatenation operations, especially string literals. In this case, the compiler may combine the concatenated operations into a single operation.
  • When an extensive search operation must be performed when generating a string. Class StringBuilder is missing search methods such as IndexOf or StartsWith. For these operations, the StringBuilder object must be converted to a String, which can negate the performance benefits of using StringBuilder. For more information, see Searching for Text Parts in StringBuilder Objects.

Consider using the StringBuilder class in the following situations:

  • If the code is expected to make an unknown number of changes to the string at design time, for example, when using a loop to concatenate a random number of strings containing user input.
  • When the code is expected to make a large number of changes to strings.

In general, String is more suitable for some short and fast operations that involve concatenating strings or querying the entire string. If some strings need to be changed frequently or dynamically modified, StringBuilder is more suitable

How StringBuilder works

How does StringBuilder dynamically modify the length of a string? Suppose there is a stringBuilder with a string length of 12. If we need to Append to a string with length =20, then the StringBuilder will first throw the string into the buffer with a length of 16. When the length exceeds the length of the buffer, It means that a larger buffer is needed, and StringBuilder will find a new buffer with twice the buffer size (now 32). Then copy the value of the old buffer and add those new characters that exceed the original length but have not been stored in the old buffer. If it still exceeds the limit, repeat the above process until the storage is completed. (If the set maximum capacity is exceeded or there is no extra space in the memory, an error will be reported)

public class Example
{
    
    
   public static void Main()
   {
    
    
      StringBuilder sb = new StringBuilder();
      ShowSBInfo(sb);
      sb.Append("This is a sentence.");
      ShowSBInfo(sb);
      for (int ctr = 0; ctr <= 10; ctr++) {
    
    
         sb.Append("This is an additional sentence.");
         ShowSBInfo(sb);
      }   
   }
   
   private static void ShowSBInfo(StringBuilder sb)
   {
    
    
      foreach (var prop in sb.GetType().GetProperties()) {
    
    
         if (prop.GetIndexParameters().Length == 0)
            Console.Write("{0}: {1:N0}    ", prop.Name, prop.GetValue(sb));
      }
      Console.WriteLine();
   }
}
// The example displays the following output:
//    Capacity: 16    MaxCapacity: 2,147,483,647    Length: 0
//    Capacity: 32    MaxCapacity: 2,147,483,647    Length: 19
//    Capacity: 64    MaxCapacity: 2,147,483,647    Length: 50
//    Capacity: 128    MaxCapacity: 2,147,483,647    Length: 81
//    Capacity: 128    MaxCapacity: 2,147,483,647    Length: 112
//    Capacity: 256    MaxCapacity: 2,147,483,647    Length: 143
//    Capacity: 256    MaxCapacity: 2,147,483,647    Length: 174
//    Capacity: 256    MaxCapacity: 2,147,483,647    Length: 205
//    Capacity: 256    MaxCapacity: 2,147,483,647    Length: 236
//    Capacity: 512    MaxCapacity: 2,147,483,647    Length: 267
//    Capacity: 512    MaxCapacity: 2,147,483,647    Length: 298
//    Capacity: 512    MaxCapacity: 2,147,483,647    Length: 329
//    Capacity: 512    MaxCapacity: 2,147,483,647    Length: 360

Methods provided by StringBuilder

It is possible to make individual method calls and ignore the return value, as shown in the following example.

using System;
using System.Text;

public class Example
{
    
    
   public static void Main()
   {
    
    
      StringBuilder sb = new StringBuilder();
      sb.Append("This is the beginning of a sentence, "); 
      sb.Replace("the beginning of ", ""); //替换所有字符A为字符B
      sb.Insert(sb.ToString().IndexOf("a ") + 2, "complete ");
      sb.Replace(",", "."); 
      Console.WriteLine(sb.ToString()); //只有在必须接受string类型时再转化为string
   }
}
// The example displays the following output:
//        This is a complete sentence.

A series of methods can be called in a single statement. This can be convenient if you want to write a single statement that links consecutive operations. The following example combines the three method calls from the previous example into a single line of code.

using System;
using System.Text;

public class Example
{
    
    
   public static void Main()
   {
    
    
      StringBuilder sb = new StringBuilder("This is the beginning of a sentence, ");
      sb.Replace("the beginning of ", "").Insert(sb.ToString().IndexOf("a ") + 2, 
                                                 "complete ").Replace(",", ".");
      Console.WriteLine(sb.ToString());
   }
}
// The example displays the following output:
//        This is a complete sentence.

access characters

Accessing characters is a big pain point with StringBuilder in my opinion. StringBuilder does not provide a method to access its internal characters, but it is not that simple to access a certain character in it, because the memory of the buffer is discontinuous. If we want to find a certain character, we need to traverse the entire buffer. Therefore, a better method is ToStringto convert it into Stringa type through a method and then use it char[Index]to access the corresponding characters.

iterate characters

When iterating over the characters of a StringBuilder, it should be noted that even for large "chunks" of StringBuilder objects, the performance impact of using the Chars[] property for index-based access of one or a small number of characters is negligible; typically, this is an O(n ) operate. When iterating characters in a StringBuilder object, there is a significant impact on performance, which is an O(n^2) (traversing n characters * buffer capacity n) operation.

Therefore, when we need to iterate the characters of StringBuilder, the better way is to ToStringconvert them into Stringtypes through methods and then use them char[Index]to access the corresponding characters.

Query characters

There is no method to query characters in StringBuilder. If you want to query characters, you can only convert to String, and then use the String.IndexOfor String.StartWithmethod to find the corresponding character or string.

Since String and StringBuilder provide too many methods, we cannot go into depth here. It is recommended to read the official documentation.


dynamic

Finally, learn a little about dynamic dynamic types. dynamic itself is also an Object. In most cases, dynamic types behave similarly to object types. Specifically, any non-Null expression can be converted to dynamic type. The dynamic type differs from object in that the compiler does not parse or type check operations on expressions containing type dynamic. The compiler packages together information about the operation, which is then used to evaluate the operation at runtime. During this process, dynamic type variables are compiled into object type variables. Therefore, dynamic types only exist at compile time and not at run time.

The special thing about dynamic is that it will not be parsed at compile time, so no security checks will be performed. Therefore, even if the wrong dynamic is defined, the compiler will not report an error. An error will only be reported when an error occurs during runtime.

Secondly, since the essence of dynamic is Object, it can also be implicitly converted to any type. And this is also its greatest advantage. For example:

dynamic x = 10; //此时x为int
x = x + "Hello"; // x 现在是一个字符串
x = x.ToUpper(); // x 仍然是一个字符串
x = 8;  // x 现在保存的是一个int类型的变量
x = x * 8; // x现在仍然是int

In the above example, we define x as dynamic. It can be seen that it should be of type int. Then we convert it into a string and then operate on the string. Then x is assigned to type int. x changes its type dynamically throughout the program. This is something that var cannot do, because the compiler will automatically infer its type under the var keyword, so it is a static class. Generally, we cannot perform type conversion without explicit conversion.

If you want to implement it using only static classes, you need to create new variables corresponding to the designed static types. If you want to implement the above process for static type variables x, it will only be more complicated:

int x=10;
String y = x.ToString();
y=y+"Hello";
y = y.ToUpper();
x = 8;
x = x* 8

The dynamic type of dynamic is actually very similar to the variable nature of some scripting languages. Therefore, we also use dynamic types to interface with scripting languages.

Guess you like

Origin blog.csdn.net/milu_ELK/article/details/132084539