本文只介绍了比较方法,但是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等处理方法)的更多相关文章

  1. C# 格式化字符串,日期,字符串操作汇总

    时间格式化 有时候我们要对时间进行转换,达到不同的显示效果 默认格式为:2005-6-6 14:33:34 如果要换成成200506,06-2005,2005-6-6或更多的该怎么办呢 我们要用到:D ...

  2. .NET面试题解析(03)-string与字符串操作

      系列文章目录地址: .NET面试题解析(00)-开篇来谈谈面试 & 系列文章索引 字符串可以说是C#开发中最常用的类型了,也是对系统性能影响很关键的类型,熟练掌握字符串的操作非常重要. 常 ...

  3. C#字符串操作大全

    ===============================字符串基本操作================================ 一.C#中字符串的建立过程 例如定义变量 strT=&qu ...

  4. java 字符串操作和日期操作

    一.字符串操作 创建字符串 String s2 = new String("Hello World"); String s1 = "Hello World"; ...

  5. Python 字符串操作及string模块使用

    python的字符串操作通过2部分的方法函数基本上就可以解决所有的字符串操作需求: python的字符串属性函数 python的string模块 1.字符串属性方法操作: 1.>字符串格式输出对 ...

  6. C语言字符串操作总结大全

    1)字符串操作 strcpy(p, p1)  复制字符串  函数原型strncpy(p, p1, n)   复制指定长度字符串  函数原型strcat(p, p1)   附加字符串  函数原型strn ...

  7. C语言字符串操作总结大全(超详细)

    本篇文章是对C语言字符串操作进行了详细的总结分析,需要的朋友参考下 1)字符串操作  strcpy(p, p1) 复制字符串  strncpy(p, p1, n) 复制指定长度字符串  strcat( ...

  8. c语言的字符串操作(比较详细)

    1)字符串操作 strcpy(p, p1) 复制字符串 strncpy(p, p1, n) 复制指定长度字符串 strcat(p, p1) 附加字符串 strncat(p, p1, n) 附加指定长度 ...

  9. C语言字符串操作函数集

    1)字符串操作 strcpy(p, p1) 复制字符串 strncpy(p, p1, n) 复制指定长度字符串 strcat(p, p1) 附加字符串 strncat(p, p1, n) 附加指定长度 ...

随机推荐

  1. 如何在CentOS7上安装Python3及对应问题

    首先一般来说安装好的CentOS是会自带python2.7,但是是没有安装python3的环境的 [root@host bin]# pwd /usr/bin [root@host bin]# ls p ...

  2. 阿里云oss怎么上传文件夹

    最近公司在做工程项目,实现文件夹云存储上传 网上找了很久,发现很多项目都存在一些问题,但还是让我找到了一个成熟的项目. 工程: 对项目的文件夹云存储上传功能做出分析,找出文件夹上传的原理,对文件夹的云 ...

  3. 用jquery制作一个二级导航下拉菜单

    1使用$(function(){...})获取到想要作用的HTML元素. 2通过使用children()方法寻找子元素.       3通过使用show()方法来显示HTML元素.       4通过 ...

  4. 【python-字典】判断python字典中key是否存在的

    一般有两种通用做法: 第一种方法:使用自带函数实现: 在python的字典的属性方法里面有一个has_key()方法: #生成一个字典 d = {'name':Tom, 'age':10, 'Tel' ...

  5. C/C++ 打开串口和关闭串口

    通常使用下列函数来通过Win系统来对外围设备进行通信处理: 0. 前言 做串口方面的程序,使用CreateFile打开串口通信端口.在对串口操作之前,需要首先打开串口.使用C++进行串口编程,如果采用 ...

  6. EntityFramework Core 学习扫盲

    0. 写在前面 1. 建立运行环境 2. 添加实体和映射数据库 1. 准备工作 2. Data Annotations 3. Fluent Api 3. 包含和排除实体类型 1. Data Annot ...

  7. MySQL--REPALCE INTO操作

    REPLACE INTO语法是MySQL数据库独特的扩展语法,可以提供“不存在即插入,存在即更新”的操作,MySQL官方文档解析其算法为: 1.尝试进行INSER 操作 2.如果INSERT 失败,则 ...

  8. Git之初识

    我的Github地址:https://github.com/shinianzongjishinianxin 初见总是美好的,可是我第一次看到github有点纠结,因为看不懂,然而最终半蒙半猜还是注册完 ...

  9. Windows的cmd窗口显示utf8字符

    用XeLaTeX的时候,查字体需要用fc-list命令,XeLaTeX用的都是utf编码,所以fc-list输出的字体信息也是utf编码.因此需要把cmd窗口也改成utf8编码才能看到这些字体信息.U ...

  10. 【NumberValidators】工商营业执照号码和统一社会信用代码验证

    从本质上讲,工商营业执照号码和统一社会信用代码是两套完全不一样的编码规则,识别结果也仅有行政区划部分为两者共有,但因为这两种编码同时存在的原因,所以如果需要在系统中唯一标志一家企业时,还是可以通过工商 ...