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) 附加指定长度 ...
随机推荐
- 分布式的CAP理论
CAP是强一致性.可用性(实时可用).分区容忍性: Consistency(一致性). Availability(可用性).Partition tolerance(分区容错性) 一般来说 P 是前提. ...
- python_day1_python简单介绍
一.python解释器的种类 我们都知道python是一种解释型的语言,那python在执行的过程中必须要通过解释器来执行,那python的解释器到底分为哪些呢? 1.Cpython CPython是 ...
- PHP与Python哪个做网站产品好?
虽然python现在比较火,但在传统的LAMP组合里Linux+apache/tomcat+MySql+PHP里是PHP做网站的脚本语言,但现在已经变了:https://baike.baidu.com ...
- dropzone 上传插件
dropzone dropzone.js是一个可预览的上传文件工具,不依赖任何框架(如jQuery),且具有可定制化.实现文件拖拽上传,提供AJAX异步上传功能. 1. html文件 dropzone ...
- Linqpad工具
下载地址: http://www.linqpad.net/ 可以通过连接数据库,直接测试LINQ语句,并可以转化为Lamda .SQL语句. 非常好用的小工具,记录一下.
- Android-okhttp下载网络图片并设置壁纸
在AndroidManifest.xml配置网络访问权限: <!-- 访问网络是危险的行为 所以需要权限 --> <uses-permission android:name=&quo ...
- (leetcode162)find peak element
1题目 A peak element is an element that is greater than its neighbors. Given an input array where num[ ...
- cvpr2015总结
cvpr所有文章 http://cs.stanford.edu/people/karpathy/cvpr2015papers/ CNN Hypercolumns for Object Segmenta ...
- linux下git远程仓库的搭建
一.服务器环境 ubuntukylin-16.04-server-amd64 二.远程服务器创建一个名字叫git的用户,专门用于管理git仓库. $ adduser git 三.安装git.服务器端和 ...
- Win10远程桌面出现 身份验证错误,要求的函数不受支持,这可能是由于CredSSP加密Oracle修正 解决方法
升级至win10 最新版本10.0.17134,远程桌面连接Window Server时报错信息如下: 出现身份验证错误,要求的函数不正确,这可能是由于CredSSP加密Oracle修正. 解决方法: ...