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) 附加指定长度 ...
随机推荐
- AIX nfs简单说明
AIX 系统 NFS设置 一.NFS守护进程:NFS是通过使用许多用户级的守护进程及远程过程调用等网络应用程序来实现的.而NFS服务器及客户端的守护进程并不完全一致. 1. 作为NFS服务器所需的守护 ...
- SED单行脚本快速参考(Unix 流编辑器)
------------------------------------------------------------------------- SED单行脚本快速参考(Unix 流编辑器) 200 ...
- 一个封存Id与状态对应键值的神器,BigInteger的setBit和testBit用法实例
1,首先描述一下应用场景 比如,我们要对菜单做权限,控制不同角色菜单显示与不显示,角色为经理时,我们需要菜单id为 4,7,13,24的菜单显示,别的菜单不显示. 就是说,这时候我们要把4,7,13, ...
- _杂谈_C语言历史
早期的操作系统软件主要是用汇编语言(包括UNIX操作系统在内)编写的.由于汇编语言依赖于计算机硬件,所以程序的可读性和可移植性都比较差,所以呢,为了提高操作系统软件的可读性和可移植性,最好改用高级语言 ...
- POJ3020 Antenna Placement
Antenna Placement Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 9586 Accepted: 4736 ...
- bootstrap2.1相关文档
本节课我们主要学习一下 Bootstrap表格和按钮功能,通过内置的 CSS定义,显示各种丰富的效果. 一.表格 Bootstrap提供了一些丰富的表格样式供开发者使用. 1.基本格式 //实现基本的 ...
- MFC中处理UI界面时的注意点
最近开发时,在处理界面上遇到了下面的问题: 上位机与下位机通信时,如果出现超时,弹出MessageBox提示的情况下,更新界面上的CStatic控件会出现重影. 经过调查发现 原因是由于在UI线程中处 ...
- asp.net 子应用程序/虚拟目录 session共享
最近遇到了一个问题,我做的asp.net mvc应用程序要作为一个子应用程序部署到几个站点中,需要在本应用程序中获取站点的session值. 已经使用了session state server,并设置 ...
- 拟物设计和Angular的实现 - Material Design
Material Design是Google最新发布的跨平台统一视觉设计语言.直接翻译是物质设计,但是我更倾向于使用"拟物设计"更为准确. 据谷歌介绍,Material Desig ...
- play framework - 初识
背景 研发代码框架是play-framework框架,想看代码的话,需要学习下play框架.IDE工具的话之前一直用的idea,所以本文涉及的idea play的配置 和 一些play的简单知识 认识 ...