C# 字符串操作基本过程(Equals、Compare、EndsWith等处理方法)

Stella981
• 阅读 418

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

C# 字符串操作基本过程(Equals、Compare、EndsWith等处理方法)

C# 字符串操作基本过程(Equals、Compare、EndsWith等处理方法)

比较两个字符串是最常见的字符串操作.一般应为两个原因要比较字符串:判断相等性或者排序(通常是为了显示给用户看).判断字符串相等性或者排序时,强烈建议调用String类定义的以下方法之一,在介绍比较方法之前,下面几个参数类型必须清楚它们的含义:

StringComparison枚举:

[ComVisible(true)]
    public enum StringComparison
    {
        /// <summary>
        /// 使用区分区域性的排序规则对字符串进行排序和当前区域性对字符串进行比较(根据当前的语言文化对字符串进行排序。然后根据当前区域性对字符串进行比较,不忽略大小写)
        /// </summary>
        CurrentCulture = 0,

        /// <summary>
        /// 使用区分区域性的排序规则对字符串进行排序和当前区域性对字符串进行比较(根据当前的语言文化对字符串进行排序。然后根据当前区域性对字符串进行比较,忽略大小写)
        /// </summary>
        CurrentCultureIgnoreCase = 1,

        /// <summary>
        ///  使用区分区域性的排序规则对字符串进行排序。固定区域性对字符串进行比较(根据当前的语言文化对字符串进行排序。然后根据固定语言文化对字符串进行比较,不忽略大小写)
        /// </summary>
        InvariantCulture = 2,

        /// <summary>
        /// 使用区分区域性的排序规则对字符串进行排序。固定区域性对字符串进行比较(根据当前的语言文化对字符串进行排序。然后根据固定语言文化对字符串进行比较,忽略大小写)
        /// </summary>
        InvariantCultureIgnoreCase = 3,

        /// <summary>
        ///  忽略语言文化,使用序号(二进制)排序规则比较字符串。
        /// </summary>
        Ordinal = 4,

        /// <summary>
        /// 忽略语言文化,通过使用序号(二进制)区分区域性的排序规则并忽略所比较的字符串的大小写,来比较字符串。
        /// </summary>
        OrdinalIgnoreCase = 5
    }

 CompareOptions枚举:

字符串比较的规则,一般在设置完比较字符串的语言文化背景之后,在设置该规则.

/// <summary>
    /// 定义要使用的字符串比较选项 System.Globalization.CompareInfo
    /// </summary>
    [Flags]
    public enum CompareOptions
    {

        /// <summary>
        /// 指示字符串比较的默认选项设置。
        /// </summary>
        None = 0,

        /// <summary>
        /// 指示字符串比较必须忽略大小写。
        /// </summary>
        IgnoreCase = 1,

        /// <summary>
        /// 指示字符串比较必须忽略非空格组合字符,如标注字符。 Unicode Standard 将组合字符定义为与基的字符,以生成新的字符组合的字符。 非空格组合字符不在呈现时本身会占用空间位置。
        /// </summary>
        IgnoreNonSpace = 2,

        /// <summary>
        /// 指示字符串比较必须忽略符号,如空白字符、 标点、 货币符号、 百分比符号,数学符号、 的与符号,依次类推。
        /// </summary>
        IgnoreSymbols = 4,

        /// <summary>
        /// 指示字符串比较必须忽略假名类型。 假名类型引用为日文平假名和片假名字符,表示在日语中的语音。 平假名用于本机日语表达式和单词,而片假名用于从"计算机"或"Internet"等其他语言借用的词语。 拼音声音可以表示在平假名和片假名。 如果选择此值,则一种声音的平假名字符视为相等的同一个声音的片假名字符。
        /// </summary>
        IgnoreKanaType = 8,

        /// <summary>
        /// 指示字符串比较必须忽略字符宽度。 例如,日语的片假名字符可以编写为全角或半角。 如果选择此值,则片假名字符的全角形式视为相等半角形式编写的相同字符。
        /// </summary>
        IgnoreWidth = 16,

        /// <summary>
        /// 字符串比较必须忽略大小写,然后执行序号比较。 此方法相当于将转换为大写使用固定区域性,然后对结果执行序号比较的字符串。
        /// </summary>
        OrdinalIgnoreCase = 268435456,

        /// <summary>
        /// 指示字符串比较必须使用字符串排序算法。 在字符串排序、 连字符和撇号,以及其他非字母数字的符号,排在字母数字字符之前。
        /// </summary>
        StringSort = 536870912,

        /// <summary>
        /// 指示字符串比较必须使用 Unicode utf-16 编码的连续值的字符串 (由代码单元比较代码单位),从而导致比较速度,但不区分区域性。 字符串与代码单元
        //   XXXX 开始16 YYYY 开头的字符串之前16, ,如果 XXXX16 小于 YYYY16。 此值不能与其他组合 System.Globalization.CompareOptions值,并必须单独使用。
        /// </summary>
        Ordinal = 1073741824
    }

(1)、Compare方法

第一种:

C# 字符串操作基本过程(Equals、Compare、EndsWith等处理方法)

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

CultureInfo.CurrentCulture代码如下:

C# 字符串操作基本过程(Equals、Compare、EndsWith等处理方法)

注:返回的是当前线程的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();

 第二种:

 C# 字符串操作基本过程(Equals、Compare、EndsWith等处理方法)

该方法是根据当前线程的语言文化,先对两个字符串进行排序,然后对排完序两个字符串判断是否相等。比较规则为是否设置大小写.

具体调用过程和第一种方法一样,区别就是判断过程中的大小写设置,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

第三种:

C# 字符串操作基本过程(Equals、Compare、EndsWith等处理方法)

该方法是根据当前线程的语言文化,先对两个字符串进行排序,然后对排完序两个字符串判断是否相等。比较规则为是否设置大小写.具体设置参数见上面的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"));
}

注:

C# 字符串操作基本过程(Equals、Compare、EndsWith等处理方法)

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

第四种:

C# 字符串操作基本过程(Equals、Compare、EndsWith等处理方法)

根据设置的语言文化,对字符串进行排序,然后比较两个字符串,比较规则为是否设置大小写忽略

该方法的代码执行比较过程和第一种方法一样.

调用代码如下:

//输出结果 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

第五种:

C# 字符串操作基本过程(Equals、Compare、EndsWith等处理方法)

根据设置的语言文化,对字符串进行排序,然后比较两个字符串,比较规则为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

第六种:

C# 字符串操作基本过程(Equals、Compare、EndsWith等处理方法)

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

第七种:

实例方法

C# 字符串操作基本过程(Equals、Compare、EndsWith等处理方法)

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方法

第一种:

C# 字符串操作基本过程(Equals、Compare、EndsWith等处理方法)

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();

C# 字符串操作基本过程(Equals、Compare、EndsWith等处理方法)

 第二种:

 C# 字符串操作基本过程(Equals、Compare、EndsWith等处理方法) ,代码如下:

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));

C# 字符串操作基本过程(Equals、Compare、EndsWith等处理方法)

结合第一种方法分析,发现第二种方法等同于:

Console.WriteLine("str和str1相等吗?答案:{0}", String.Equals(str, str1, StringComparison.Ordinal));

有如下佐证:

C# 字符串操作基本过程(Equals、Compare、EndsWith等处理方法)

C# 字符串操作基本过程(Equals、Compare、EndsWith等处理方法)

注: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));

C# 字符串操作基本过程(Equals、Compare、EndsWith等处理方法)

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

C# 字符串操作基本过程(Equals、Compare、EndsWith等处理方法)

第五种:第三种和第二种的特殊版本

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等处理方法)

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Wesley13 Wesley13
3年前
java将前端的json数组字符串转换为列表
记录下在前端通过ajax提交了一个json数组的字符串,在后端如何转换为列表。前端数据转化与请求varcontracts{id:'1',name:'yanggb合同1'},{id:'2',name:'yanggb合同2'},{id:'3',name:'yang
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
待兔 待兔
5个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Jacquelyn38 Jacquelyn38
3年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Wesley13 Wesley13
3年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Wesley13 Wesley13
3年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Stella981 Stella981
3年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
11个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这