C# 字符串操作基本过程(Equals、Compare、EndsWith等处理方法)
本文只介绍了比较方法,但是EndsWith,IndexOf等方法均采用相同的过程,先设置CultureInfo(一般情况下调用当前线程的CultureInfo,该语言文化可以通过控制面板设置),然后调用CultureInfo实例下面的CompareInfo属性,实例化语言/国家的CompareInfo实例,并调用对应的字符串操作方法.


比较两个字符串是最常见的字符串操作.一般应为两个原因要比较字符串:判断相等性或者排序(通常是为了显示给用户看).判断字符串相等性或者排序时,强烈建议调用String类定义的以下方法之一,在介绍比较方法之前,下面几个参数类型必须清楚它们的含义:
StringComparison枚举:
[ComVisible(true)]
public enum StringComparison
{
/// <summary>
/// 使用区分区域性的排序规则对字符串进行排序和当前区域性对字符串进行比较(根据当前的语言文化对字符串进行排序。然后根据当前区域性对字符串进行比较,不忽略大小写)
/// </summary>
CurrentCulture = , /// <summary>
/// 使用区分区域性的排序规则对字符串进行排序和当前区域性对字符串进行比较(根据当前的语言文化对字符串进行排序。然后根据当前区域性对字符串进行比较,忽略大小写)
/// </summary>
CurrentCultureIgnoreCase = , /// <summary>
/// 使用区分区域性的排序规则对字符串进行排序。固定区域性对字符串进行比较(根据当前的语言文化对字符串进行排序。然后根据固定语言文化对字符串进行比较,不忽略大小写)
/// </summary>
InvariantCulture = , /// <summary>
/// 使用区分区域性的排序规则对字符串进行排序。固定区域性对字符串进行比较(根据当前的语言文化对字符串进行排序。然后根据固定语言文化对字符串进行比较,忽略大小写)
/// </summary>
InvariantCultureIgnoreCase = , /// <summary>
/// 忽略语言文化,使用序号(二进制)排序规则比较字符串。
/// </summary>
Ordinal = , /// <summary>
/// 忽略语言文化,通过使用序号(二进制)区分区域性的排序规则并忽略所比较的字符串的大小写,来比较字符串。
/// </summary>
OrdinalIgnoreCase =
}
CompareOptions枚举:
字符串比较的规则,一般在设置完比较字符串的语言文化背景之后,在设置该规则.
/// <summary>
/// 定义要使用的字符串比较选项 System.Globalization.CompareInfo
/// </summary>
[Flags]
public enum CompareOptions
{ /// <summary>
/// 指示字符串比较的默认选项设置。
/// </summary>
None = , /// <summary>
/// 指示字符串比较必须忽略大小写。
/// </summary>
IgnoreCase = , /// <summary>
/// 指示字符串比较必须忽略非空格组合字符,如标注字符。 Unicode Standard 将组合字符定义为与基的字符,以生成新的字符组合的字符。 非空格组合字符不在呈现时本身会占用空间位置。
/// </summary>
IgnoreNonSpace = , /// <summary>
/// 指示字符串比较必须忽略符号,如空白字符、 标点、 货币符号、 百分比符号,数学符号、 的与符号,依次类推。
/// </summary>
IgnoreSymbols = , /// <summary>
/// 指示字符串比较必须忽略假名类型。 假名类型引用为日文平假名和片假名字符,表示在日语中的语音。 平假名用于本机日语表达式和单词,而片假名用于从"计算机"或"Internet"等其他语言借用的词语。 拼音声音可以表示在平假名和片假名。 如果选择此值,则一种声音的平假名字符视为相等的同一个声音的片假名字符。
/// </summary>
IgnoreKanaType = , /// <summary>
/// 指示字符串比较必须忽略字符宽度。 例如,日语的片假名字符可以编写为全角或半角。 如果选择此值,则片假名字符的全角形式视为相等半角形式编写的相同字符。
/// </summary>
IgnoreWidth = , /// <summary>
/// 字符串比较必须忽略大小写,然后执行序号比较。 此方法相当于将转换为大写使用固定区域性,然后对结果执行序号比较的字符串。
/// </summary>
OrdinalIgnoreCase = , /// <summary>
/// 指示字符串比较必须使用字符串排序算法。 在字符串排序、 连字符和撇号,以及其他非字母数字的符号,排在字母数字字符之前。
/// </summary>
StringSort = , /// <summary>
/// 指示字符串比较必须使用 Unicode utf-16 编码的连续值的字符串 (由代码单元比较代码单位),从而导致比较速度,但不区分区域性。 字符串与代码单元
// XXXX 开始16 YYYY 开头的字符串之前16, ,如果 XXXX16 小于 YYYY16。 此值不能与其他组合 System.Globalization.CompareOptions值,并必须单独使用。
/// </summary>
Ordinal =
}
(1)、Compare方法
第一种:

该方法是根据当前线程的语言文化,先对两个字符串进行排序,然后判断排完序之后的两个字符串是否相等,比较规则(具体设置见 CompareOptions枚举)为默认规则.
CultureInfo.CurrentCulture代码如下:

注:返回的是当前线程的CurrentCulture实例属性,该实例属性返回一个全局CultureInfo对象,接着调用CompareInfo属性,返回一个CompareInfo对象,最后调用Compare方法,Compare方法如下:
public virtual int Compare(string string1, string string2, CompareOptions options)
{
if (options == CompareOptions.OrdinalIgnoreCase)
{
return string.Compare(string1, string2, StringComparison.OrdinalIgnoreCase);
}
if ((options & CompareOptions.Ordinal) != CompareOptions.None)
{
if (options != CompareOptions.Ordinal)
{
throw new ArgumentException(Environment.GetResourceString("Argument_CompareOptionOrdinal"), "options");
}
return string.CompareOrdinal(string1, string2);
}
if ((options & ~(CompareOptions.StringSort | CompareOptions.IgnoreWidth | CompareOptions.IgnoreKanaType | CompareOptions.IgnoreSymbols | CompareOptions.IgnoreNonSpace | CompareOptions.IgnoreCase)) != CompareOptions.None)
{
throw new ArgumentException(Environment.GetResourceString("Argument_InvalidFlag"), "options");
}
if (string1 == null)
{
if (string2 == null)
{
return 0;
}
return -1;
}
if (string2 == null)
{
return 1;
}
return InternalCompareString(this.m_dataHandle, this.m_handleOrigin, this.m_sortName, string1, 0, string1.Length, string2, 0, string2.Length, GetNativeCompareFlags(options));
}
InternalCompareString方法位extern方法,所以无法继续查看源码.
调用代码:
string a = "aaa";
string b = "bbb";
string c = "aaa";
//输出结果 0-代表相等 -1-代表在当前线程的语言文化的排序结果是a比b小 1-代表在当前线程的语言文化的排序结果是a比b大
Console.WriteLine(string.Compare(a, b));//输出:-1
Console.WriteLine(string.Compare(a, c));//输出:0 //对null值的特殊处理
Console.WriteLine(string.Compare(null, null));//输出:0
Console.WriteLine(string.Compare(a, null));//输出:1
Console.WriteLine(string.Compare(null, a));//输出:-1
Console.ReadKey();
第二种:

该方法是根据当前线程的语言文化,先对两个字符串进行排序,然后对排完序两个字符串判断是否相等。比较规则为是否设置大小写.
具体调用过程和第一种方法一样,区别就是判断过程中的大小写设置,ignoreCase为false,则走第一种方法的比较过程.
调用代码:
//输出结果 0-代表相等 -1-代表在当前线程的语言文化的排序结果是a比b小 1-代表在当前线程的语言文化的排序结果是a比b大
string a = "aaa";
string c = "AAA";
Console.WriteLine(string.Compare(a, c,true));//输出:0 //对null值的特殊处理
Console.WriteLine(string.Compare(null, null,true));//输出:0
Console.WriteLine(string.Compare(a, null,true));//输出:1
Console.WriteLine(string.Compare(null, a,true));//输出:-1
第三种:

该方法是根据当前线程的语言文化,先对两个字符串进行排序,然后对排完序两个字符串判断是否相等。比较规则为是否设置大小写.具体设置参数见上面的StringComparison枚举.
public static int Compare(string strA, string strB, StringComparison comparisonType)
{
if ((comparisonType - 0) > StringComparison.OrdinalIgnoreCase)
{
throw new ArgumentException(Environment.GetResourceString("NotSupported_StringComparison"), "comparisonType");
}
if (strA == strB)
{
return 0;
}
if (strA == null)
{
return -1;
}
if (strB == null)
{
return 1;
}
switch (comparisonType)
{
case StringComparison.CurrentCulture:
return CultureInfo.CurrentCulture.CompareInfo.Compare(strA, strB, CompareOptions.None); case StringComparison.CurrentCultureIgnoreCase:
return CultureInfo.CurrentCulture.CompareInfo.Compare(strA, strB, CompareOptions.IgnoreCase); case StringComparison.InvariantCulture:
return CultureInfo.InvariantCulture.CompareInfo.Compare(strA, strB, CompareOptions.None); case StringComparison.InvariantCultureIgnoreCase:
return CultureInfo.InvariantCulture.CompareInfo.Compare(strA, strB, CompareOptions.IgnoreCase); case StringComparison.Ordinal:
if ((strA.m_firstChar - strB.m_firstChar) == 0)
{
return CompareOrdinalHelper(strA, strB);
}
return (strA.m_firstChar - strB.m_firstChar); case StringComparison.OrdinalIgnoreCase:
if (!strA.IsAscii() || !strB.IsAscii())
{
return TextInfo.CompareOrdinalIgnoreCase(strA, strB);
}
return CompareOrdinalIgnoreCaseHelper(strA, strB);
}
throw new NotSupportedException(Environment.GetResourceString("NotSupported_StringComparison"));
}
注:

不走第一种方法的流程,直接比较字符串的二进制大小.
第四种:

根据设置的语言文化,对字符串进行排序,然后比较两个字符串,比较规则为是否设置大小写忽略
该方法的代码执行比较过程和第一种方法一样.
调用代码如下:
//输出结果 0-代表相等 -1-代表在当前线程的语言文化的排序结果是a比b小 1-代表在当前线程的语言文化的排序结果是a比b大
string a = "aaa";
string c = "AAA";
Console.WriteLine(string.Compare(a, c,true,CultureInfo.CurrentCulture));//输出:0 //对null值的特殊处理
Console.WriteLine(string.Compare(null, null,true, CultureInfo.CurrentCulture));//输出:0
Console.WriteLine(string.Compare(a, null,true, CultureInfo.CurrentCulture));//输出:1
Console.WriteLine(string.Compare(null, a,true, CultureInfo.CurrentCulture));//输出:-1
第五种:

根据设置的语言文化,对字符串进行排序,然后比较两个字符串,比较规则为CompareOptions设置的规则,具体请参考CompareOptions枚举
该方法的代码执行比较过程和第一种方法一样.
调用代码:
//输出结果 0-代表相等 -1-代表在当前线程的语言文化的排序结果是a比b小 1-代表在当前线程的语言文化的排序结果是a比b大
string a = "aaa";
string c = "AAA";
Console.WriteLine(string.Compare(a,c,CultureInfo.CurrentCulture,CompareOptions.IgnoreCase));//输出:0
第六种:

加了截取字符串的功能,可判断从字符串的指定位置开始比较字符串的异同和大小,其余流程和上面的方法一样.
第七种:
实例方法

public int CompareTo(object value)
{
if (value == null)
{
return 1;
}
if (!(value is string))
{
throw new ArgumentException(Environment.GetResourceString("Arg_MustBeString"));
}
return Compare(this, (string) value, StringComparison.CurrentCulture);
}
调用代码:
//输出结果 0-代表相等 -1-代表在当前线程的语言文化的排序结果是a比b小 1-代表在当前线程的语言文化的排序结果是a比b大
string a = "aaa";
string c = "aaa";
Console.WriteLine(a.CompareTo(c));//输出:0
(2)、Equals方法
第一种:

StringComparsion参数上面有说明:
public static bool Equals(string a, string b, StringComparison comparisonType)
{
if ((comparisonType < StringComparison.CurrentCulture) || (comparisonType > StringComparison.OrdinalIgnoreCase))
{
throw new ArgumentException(Environment.GetResourceString("NotSupported_StringComparison"), "comparisonType");
}
if (a == b)
{
return true;
}
if ((a == null) || (b == null))
{
return false;
}
switch (comparisonType)
{
case StringComparison.CurrentCulture:
return (CultureInfo.CurrentCulture.CompareInfo.Compare(a, b, CompareOptions.None) == 0); case StringComparison.CurrentCultureIgnoreCase:
return (CultureInfo.CurrentCulture.CompareInfo.Compare(a, b, CompareOptions.IgnoreCase) == 0); case StringComparison.InvariantCulture:
return (CultureInfo.InvariantCulture.CompareInfo.Compare(a, b, CompareOptions.None) == 0); case StringComparison.InvariantCultureIgnoreCase:
return (CultureInfo.InvariantCulture.CompareInfo.Compare(a, b, CompareOptions.IgnoreCase) == 0); case StringComparison.Ordinal:
return ((a.Length == b.Length) && EqualsHelper(a, b)); case StringComparison.OrdinalIgnoreCase:
if (a.Length == b.Length)
{
if (a.IsAscii() && b.IsAscii())
{
return (CompareOrdinalIgnoreCaseHelper(a, b) == 0);
}
return (TextInfo.CompareOrdinalIgnoreCase(a, b) == 0);
}
return false;
}
throw new ArgumentException(Environment.GetResourceString("NotSupported_StringComparison"), "comparisonType");
}
根据设置的语言文化,对字符串进行排序,然后比较两个字符串,比较规则为固定的规则,和Compare比较方法一致.
调用代码:
var str = "aaa";
var str1 = "aaa";
Console.WriteLine("根据当前的语言文化对字符串进行排序。然后根据当前区域性对字符串进行比较,不忽略大小写的规则判断str和str1是否相等? 结果:{0}", String.Equals(str, str1, StringComparison.CurrentCulture));
Console.WriteLine("根据当前的语言文化对字符串进行排序。然后根据当前区域性对字符串进行比较,忽略大小写的规则判断str和str1是否相等? 结果:{0}", String.Equals(str, str1, StringComparison.CurrentCultureIgnoreCase));
Console.WriteLine("根据当前的语言文化对字符串进行排序。然后根据固定语言文化对字符串进行比较,不忽略大小写的规则判断str和str1是否相等? 结果:{0}", String.Equals(str, str1, StringComparison.InvariantCulture));
Console.WriteLine("根据当前的语言文化对字符串进行排序。然后根据固定语言文化对字符串进行比较,忽略大小写的规则判断str和str1是否相等? 结果:{0}", String.Equals(str, str1, StringComparison.InvariantCultureIgnoreCase));
Console.WriteLine("忽略语言文化,使用序号(二进制)排序规则比较字符串。判断str和str1是否相等? 结果:{0}", String.Equals(str, str1, StringComparison.Ordinal));
Console.WriteLine("忽略语言文化,通过使用序号(二进制)区分区域性的排序规则并忽略所比较的字符串的大小写,来比较字符串。判断str和str1是否相等? 结果:{0}", String.Equals(str, str1, StringComparison.OrdinalIgnoreCase));
Console.ReadKey();

第二种:
,代码如下:
public static bool Equals(string a, string b)
{
if (a == b)
{
return true;
}
if ((a == null) || (b == null))
{
return false;
}
if (a.Length != b.Length)
{
return false;
}
return EqualsHelper(a, b);
}
var str = "aaa";
var str1 = "aaa";
Console.WriteLine("str和str1相等吗?答案:{0}", String.Equals(str, str1));

结合第一种方法分析,发现第二种方法等同于:
Console.WriteLine("str和str1相等吗?答案:{0}", String.Equals(str, str1, StringComparison.Ordinal));
有如下佐证:


注:StringComparison.Ordinal这种方式强制忽略语言文化比较字符串的大小,是字符串比较最快的方式.
第三种:第二种静态版本的实例实现版本
public bool Equals(string value)
{
if (this == null)
{
throw new NullReferenceException();
}
if (value == null)
{
return false;
}
if (this == value)
{
return true;
}
if (this.Length != value.Length)
{
return false;
}
return EqualsHelper(this, value);
}
调用方式:
var str = "aaa";
var str1 = "aaa";
Console.WriteLine("str和str1相等吗?答案:{0}", str.Equals(str1));

第四种:第一种静态版本的实例实现版本

第五种:第三种和第二种的特殊版本
public override bool Equals(object obj)
{
if (this == null)
{
throw new NullReferenceException();
}
string strB = obj as string;
if (strB == null)
{
return false;
}
if (this == obj)
{
return true;
}
if (this.Length != strB.Length)
{
return false;
}
return EqualsHelper(this, strB);
}
虽然传入的是obj,但是将obj转换成了string,然后执行EqualsHelper方法.
注:
(1)、许多程序都将字符串用于内部编程目的,比如路径名、文件名、URL、注册表项/值、环境变量、反射、XML标记、XML特性等.
这些字符串通常只在程序内部使用,不向用户显示.出于编程目的比较字符串,使用StringComparsion.Ordinal或者StringComparison.OrdinalIgnoreCase是最好的,因为忽略文化是字符串比较最快的方式.
(2)、但是要以语言文化正确的方式来比较字符串(通常是为了向用户显示),就应该使用StringComparsion.CurrentCultrue或者StringComparsion.CurrentCultrueIgnoreCase.
(3)、StringComparsion.InvariantCultrue和StringComparsion.InvariantCultrueIgnoreCase慎用,虽然这两个值能保证比较时语言文化的正确性,但用来比较内部编程所需的字符串,所花的时间远超出序号比较,也就是Ordinal和OrdinalIgnoreCase的比较方式.在处理要想用户显示的字符串时,选择它也不恰当,因为它代表不适用任何具体的语言文化.
(4)、

C# 字符串操作基本过程(Equals、Compare、EndsWith等处理方法)的更多相关文章
- C# 格式化字符串,日期,字符串操作汇总
时间格式化 有时候我们要对时间进行转换,达到不同的显示效果 默认格式为:2005-6-6 14:33:34 如果要换成成200506,06-2005,2005-6-6或更多的该怎么办呢 我们要用到:D ...
- .NET面试题解析(03)-string与字符串操作
系列文章目录地址: .NET面试题解析(00)-开篇来谈谈面试 & 系列文章索引 字符串可以说是C#开发中最常用的类型了,也是对系统性能影响很关键的类型,熟练掌握字符串的操作非常重要. 常 ...
- C#字符串操作大全
===============================字符串基本操作================================ 一.C#中字符串的建立过程 例如定义变量 strT=&qu ...
- java 字符串操作和日期操作
一.字符串操作 创建字符串 String s2 = new String("Hello World"); String s1 = "Hello World"; ...
- Python 字符串操作及string模块使用
python的字符串操作通过2部分的方法函数基本上就可以解决所有的字符串操作需求: python的字符串属性函数 python的string模块 1.字符串属性方法操作: 1.>字符串格式输出对 ...
- C语言字符串操作总结大全
1)字符串操作 strcpy(p, p1) 复制字符串 函数原型strncpy(p, p1, n) 复制指定长度字符串 函数原型strcat(p, p1) 附加字符串 函数原型strn ...
- C语言字符串操作总结大全(超详细)
本篇文章是对C语言字符串操作进行了详细的总结分析,需要的朋友参考下 1)字符串操作 strcpy(p, p1) 复制字符串 strncpy(p, p1, n) 复制指定长度字符串 strcat( ...
- c语言的字符串操作(比较详细)
1)字符串操作 strcpy(p, p1) 复制字符串 strncpy(p, p1, n) 复制指定长度字符串 strcat(p, p1) 附加字符串 strncat(p, p1, n) 附加指定长度 ...
- C语言字符串操作函数集
1)字符串操作 strcpy(p, p1) 复制字符串 strncpy(p, p1, n) 复制指定长度字符串 strcat(p, p1) 附加字符串 strncat(p, p1, n) 附加指定长度 ...
随机推荐
- .net 根据图片网络地址获取图片二进制字节数据流
根据html路径获取图片的字节 /// <summary> ///根据html路径获取图片的字节 /// </summary> /// <param name=" ...
- Android多点触控手势基础
处理多点触控手势 多点触控就是同时把一根以上的手指放在屏幕上. 再继续往下以前需要补充一些名词: 触控手势:就是把一根或者几根手指放在屏幕上做各种动作,其中包括保留一根手指的前提下,拿起或者放下其余的 ...
- python迭代器实例
1. 迭代器 迭代器是访问集合元素的一种方式.迭代器对象从集合的第一个元素开始访问,知道所有的元素被访问完结束.迭代器只能往前不会后退,不过这也没什么,因为人们很少在迭代途中往后退. 1.1 使用迭代 ...
- MapReduce_架构
架构 MapReduce1.x JobTracker:JT(作业管理者) 将作业分解成一堆的任务:Task(MapTask和ReduceTask) 将任务分派给TaskTracker运行 作业的监控. ...
- js五道经典练习题--第四道qq好友列表
<!DOCTYPE html><html> <head> <meta charset="UTF-8"> <title>& ...
- Visual Studio Code 显示隐藏的.git文件和目录
在默认设置中,Visual Studio Code 将下列文件文件排除在显示列表中: "files.exclude": { "**/.git": true, & ...
- MySQL1安装
---恢复内容开始--- (1)安装MySQL ①ZIP安装 ②MSI安装(Windows Installer) Ⅰ 先从官网下载 目前选择使用Typical安装↑ 目前不勾选配置选项↑ 找到配置向 ...
- SignalR 2 入门
在本教程中使用的软件版本 Visual Studio 2015 .NET 4.5 SignalR 版本 2 概述 本教程介绍了通过演示如何生成简单的基于浏览器的聊天应用程序的 SignalR 开发. ...
- .netcore-FreeSql的使用-搭建context
之前用netcore搭建了一个小项目,数据库操作用的是要手写sql语句的connection和command,一直想调个EFCore或者类似SOA那样的框架 今天看到了DotNet公众号提到的.NET ...
- JQuery Mobile - 导航栏选中状态代码
class="ui-btn-active" 参考: https://wizardforcel.gitbooks.io/w3school-jqmobile/content/8.htm ...