Recently, I have been re-reading CLR via C #. This time, I will summarize the string comparison functions.
1. Compare and compareto large PK
First, we use the most common string. Compare and compareto instance methods. Let's take a look at these two methods:
We can intuitively see that the static method of string is much more overloaded than compareto. In fact, this is the biggest difference between the two, that is, String. compare has more options for us to control.
It mainly includes three aspects:
A. Cultural Information
B. compareoptions
C. start and end positions of the comparison
For cultural information, we can look at the decompilation results of compare:
For compare, it calls the corresponding comparison by passing in the cultural information.
Compareto is:
Compareto calls the cultural information associated with the current thread.
For cultural information, there is also an enumeration option: stringcomparison:
Let's take a look at the stringcomparison enumeration:
For this enumeration, there are a total of the above six enumeration values. This enumeration mainly corresponds to the current cultural information, Case sensitivity, and sorting rules.
This means that,If we use the string. Compare static method for string comparison during internationalization.
Let's take a look at compareoptions:
Finally, let's take a look at the string. Compare method containing the start and end positions:
The method itself is very simple, and the method chain uses the following at the end:
A non-hosted method that compares strings internally, but the specific content of the method is unknown, but it can be clear that,This must be an efficient comparisonAlgorithm.
Therefore, when we substring and tolower, we may use string. Compare here. Does it save us a lot of space and increase the efficiency?
Therefore, I suggest,If possible, we try to use the string. Compare method instead of the compareto method.!
2. Forgotten compareordinal
Let's take a look at the source code of compareordinal:
Private Static unsafe int Compareordinalhelper ( String Stra, String Strb)
{
Int Num = Math . Min (stra. length, strb. Length );
Int Num2 =- 1 ;
Fixed ( Char * Chref = & stra. m_firstchar)
{
Fixed ( Char * Chref2 = & strb. m_firstchar)
{
Char * Chptr = chref;
Char * Chptr2 = chref2;
While (Num> = 10 )
{
If (*((( Int *) Chptr ))! = *((( Int *) Chptr2 )))
{
Num2 = 0 ;
Break ;
}
If (*((( Int *) (Chptr + 2 )))! = *(((Int *) (Chptr2 + 2 ))))
{
Num2 = 2 ;
Break ;
}
If (*((( Int *) (Chptr + 4 )))! = *((( Int *) (Chptr2 + 4 ))))
{
Num2 =4 ;
Break ;
}
If (*((( Int *) (Chptr + 6 )))! = *((( Int *) (Chptr2 + 6 ))))
{
Num2 = 6 ;
Break ;
}
If (*(((Int *) (Chptr + 8 )))! = *((( Int *) (Chptr2 + 8 ))))
{
Num2 = 8 ;
Break ;
}
Chptr + = 10 ;
Chptr2 + = 10 ;
Num-= 10 ;
}
If (Num2 =- 1 )
{
Goto Label_00f1;
}
Chptr + = num2;
Chptr2 + = num2;
Int Num3 = chptr [ 0 ]-Chptr2 [ 0 ];
If (Num3! = 0 )
{
Return Num3;
}
Return (Chptr [ 1 ]-Chptr2 [ 1 ]);
Label_00d7:
If (*((( Int *) Chptr ))! = *((( Int *) Chptr2 )))
{
Goto Label_00f5;
}
Chptr + = 2 ;
Chptr2 + = 2 ;
Num-= 2 ;
Label_00f1:
If (Num> 0 )
{
Goto Label_00d7;
}
Label_00f5:
If (Num> 0 )
{
Int Num4 = chptr [0 ]-Chptr2 [ 0 ];
If (Num4! = 0 )
{
Return Num4;
}
Return (Chptr [ 1 ]-Chptr2 [ 1 ]);
}
Return (Stra. Length-strb. Length );
}
}
}
The method is very long, but it is very simple. Even if the variable name of reflector is BT, We can roughly look at it.
It divides the entire string into a group of five characters (10 bytes), compares them one by one, finds the first ASCII code that is not the same, and then exits the loop. And find the ASCII code difference between the two.However, I am puzzled why Microsoft is so troublesome to implement it. You have to wait until Monday to solve the problem.
However, in CLR via C #, the following statements are available:This method is faster than other methods.I think it makes sense.
So when we compare the size, try to use the compareordinal method.
3. Common equals Methods
First, let's look at the equals instance method:
The method first checks validity, and then compares whether the two point to the same reference. Next, call the equalshelper method (I don't know why Microsoft is addicted to xxxhelper. Shouldn't xxxhelper be a class name?)
Private Static unsafe bool Equalshelper ( String Stra, String Strb)
{
Int Length = stra. length;
If (Length! = Strb. length)
{
Return false ;
}
Fixed ( Char * Chref = & stra. m_firstchar)
{
Fixed ( Char * Chref2 = & strb. m_firstchar)
{
Char * Chptr = chref;
Char * Chptr2 = chref2;
While (Length> = 10 )
{
If ((((*((( Int *) Chptr ))! = *((( Int *) Chptr2) | (*((( Int *) (Chptr + 2 )))! = *((( Int *) (Chptr2 + 2 ) | ((*((( Int *) (Chptr + 4 )))! = *(((Int *) (Chptr2 + 4 ) | (*((( Int *) (Chptr + 6 )))! = *((( Int *) (Chptr2 + 6 ) | (*((( Int *) (Chptr + 8 )))! = *((( Int *) (Chptr2 + 8 )))))
{
Break ;
}
Chptr + = 10 ;
Chptr2 + = 10 ;
Length-= 10 ;
}
While (Length> 0 )
{
If (*((( Int *) Chptr ))! = *((( Int *) Chptr2 )))
{
Break ;
}
Chptr + = 2 ;
Chptr2 + = 2 ;
Length-= 2 ;
}
Return (Length <= 0 );
}
}
}
Confused, this is another algorithm. I really don't know the mysteries of 10 bytes. I will explain it if I ask the answer on Monday.
However, it is worth noting that the securityCodeTherefore, the efficiency is much higher than the security code.
Next let's take a look at the equals static method:
(The = operator has an error before being overloaded. The following will explain it clearly)
4. Summary
This article mainly introduces the comparison method of the string type, and leaves some questions. I hope you can answer them.