0. 前言

上一篇文章介绍了字符串自身的一些方法,就是对象方法。在字符串体系中,还有一些是string类提供的静态方法。这两部分构成了字符串体系,当然还有一些三方库为字符串提供了扩展方法。

这里简单的介绍一下string类的静态方法。

1. 玩转创建字符串

1.1 Create一个字符串

通过调用string.Create方法可以生成一个字符串。该方法的声明是

public static string Create<TState> (int length, TState state, System.Buffers.SpanAction<char,TState> action);

简单的来讲就是生成一个长度为length的字符串,基本元素是 TState类型的state,具体的填充过程交由action来进行处理。值得注意的是action是一个委托,也就是它可以用lambda表达式直接使用,具体声明如下:

public delegate void SpanAction<T,in TArg>(Span<T> span, TArg arg);

因为方法中指定了Span参数为char,那么 action 的写法应该如下:

(span, state)=>//span 的类型是 Span<char>,state的类型是 TState
{
// 注意,没有返回值
}

示例:

string str = "12320kz,zxcqweqwkuqwiqewpqwwe";
Console.WriteLine(string.Create(10,str, (span, c) =>
{
span.Fill(c[0]);
}));

span的方法Fill的参数是char,所以这个方法就是按照一定逻辑将 state参数转换成char然后填充给字符串,在action中多次调用Fill只会生效最后一次填充。

1.2 连接多个元素

字符串的连接有两个方法,一个是string.Concat,一个是string.Join

首先介绍Concat,这个方法最基本的功能就是将多个字符串收尾连接成一个字符串,继续引申,连接任意个对象形成一个字符串,最后将一个集合的元素拼接成字符串。所以,这个方法的声明就有以下内容:

public static string Concat (string str0, string str1);
public static string Concat (object arg0, object arg1);
public static string Concat (params string[] values);
public static string Concat (params object[] args);
public static string Concat (System.Collections.Generic.IEnumerable<string> values);
public static string Concat<T> (System.Collections.Generic.IEnumerable<T> values);

以上只是几个具有代表性的方法,介绍到这里有没有觉得它的实现很眼熟?

没错,字符串的‘加法’运算就是基于这个方法实现的。

Join在行为上与Concat很相似,但是这个方法是用一个分割符(可以是字符串)将一组对象连接起来,所以它的声明就是如下内容:

public static string Join (char separator, params object[] values);
public static string Join<T> (char separator, System.Collections.Generic.IEnumerable<T> values);
public static string Join (string separator, params object[] values);
public static string Join<T> (string separator, System.Collections.Generic.IEnumerable<T> values);

这两个方法出镜率非常高,不过Concat更多的是用‘加法’形式,而Join在多个元素快速生成字符串中非常常见。

这里简单介绍一下Join的使用:

var list = new List<int>();
for (var i = 0; i < 10; i++)
{
list.Add(i);// 生成一个列表,元素是0到9这十个数字
}
string str = string.Join(",", list);//0,1,2,3,4,5,6,7,8,9

2. 快来比一比

2.1 我们是不是同一个

因为字符串机制的问题,所以一般字符串的相等性比较分为了两种,字面相等性和引用相等性。在C#中默认的相等性比较是字面值相等性。示例:

string str1 = "123";
string str2 = "123";
string str3 = new string("123");
bool eq1 = str1 == str2;// true
bool eq2 = str2 == str3;// true
bool eq3 = str1 == str3;// true

那么如何判断是否是同一个引用呢?通过object.ReferenceEquals来判断是否是同一个引用。继续上面的例子:

bool req1 = object.ReferenceEquals(str1, str2);// true
bool req1 = object.ReferenceEquals(str2, str3);// false
bool req3 = object.ReferenceEquals(str1, str3);// false

在C#中,编译器会将一样字面值的字符串指向同一个地址,这个地址是在字符串的常量池中。而使用new等方法创建的字符串,是在程序运行后才会确认字符串具体的值,所以这个地址是后分配的。所以上述两种判断方式会出现不同的结果。

string类提供了一个静态方法Equals,方法声明如下:

public static bool Equals (string a, string b);
public static bool Equals (string a, string b, StringComparison comparisonType);

该方法返回两个字符串是否是相等的,也就是与字符串默认的==判断是一致的。

2.2 来比一比高矮

在我们开发的过程中经常会遇到对字符串进行排序的需求,那么字符串排序的逻辑是什么呢?

对于数字、字母来说是按照ASCII码进行排序的,也就是数字、小写、大写字母这样进行排序。当加入中文后,中文排最后,同种字符按字典顺序进行排序。对于一些跨语言的排序会因为语言不同而导致排序结果不一样。这里有兴趣的可以查看一下微软的官方文档。

介绍一下字符串排序的基本方法:Compare

这个方法有一个对象的相似方法是CompareTo,这个方法是IComparable接口定义的方法,与这个方法行为一致。该方法常用的有如下几个定义:

public static int Compare (string strA, string strB);
public static int Compare (string strA, string strB, StringComparison comparisonType);

这个方法返回一个整型,可以理解为两个字符串之间的距离,正的表示A在B的后面,负的表示A在B的前面。值的绝对值越大,两个字符串之间的距离也越大,但是值本身不具备意义。如果值为0,则表示这两个字符串相等。

有一个重载版本里有个参数类型是StringComparison,这是一个枚举类型,用来定义在比较两个字符串时的一些行为,后续有机会详细介绍这一部分。

示例:

string str1 = "123a";
string str2 = "132a";
int position1 = string.Compare(str1, str2);// -1
str1 = "你好";
str2 = "我们";
int position2 = string.Compare(str1, str2);// -1

可以明显看出,排序规则基本就是字典顺序。

3. 补充

补充三个上一篇文章遗漏的方法,插入、删除、获取一个子串。

3.1 插入到某个位置

public string Insert (int startIndex, string value);

在源字符串指定的位置插入一个字符串并返回插入的结果。

3.2 删除

//从startIndex开始,后面的所有元素都删除,包括startIndex,返回剩下的字符
public string Remove (int startIndex);
//从startIndex开始,删除 count个元素,返回剩下的字符
public string Remove (int startIndex, int count);

3.3 获取一个子串

// 返回从startIndex开始,剩下的的元素,包括startIndex
public string Substring (int startIndex);
// 返回从startIndex开始,一共count个元素的字符串,包括startIndex
public string Substring (int startIndex, int length);

这一部分的方法比较简单,就不做示例演示了。不过需要注意的是 所有参数都应该是大于0的,且不能大于字符串的长度,包括 startIndex+count。

4. 总结

目前为止,字符串的常规使用已经完成了,但是字符串的使用却并没有结束,后续会继续介绍C#其他内容,其中有几个内容是与字符串有很大的关联的,这里先容我卖个关子。

更多内容烦请关注我的博客

C# 基础知识系列- 9 字符串的更多用法(二)的更多相关文章

  1. C# 基础知识系列- 9 字符串的更多用法(一)

    0. 前言 在前面的文章里简单介绍了一下字符串的相关内容,并没有涉及到更多的相关内容,这一篇将尝试讲解一下在实际开发工作中会遇到的字符串的很多操作. 1. 创建一个字符串 这部分介绍一下如何创建一个字 ...

  2. C# 基础知识系列- 10 反射和泛型(二)

    0. 前言 这篇文章延续<C# 基础知识系列- 5 反射和泛型>,继续介绍C#在反射所开发的功能和做的努力.上一篇文章大概介绍了一下泛型和反射的一些基本内容,主要是通过获取对象的类型,然后 ...

  3. C# 基础知识系列- 2 字符串

    String的常见方法 String 变量的声明方式 C#中字符串常见的声明有两种: 直接使用字面值 即String s = "12321"; 使用构造器,即String s = ...

  4. C# 基础知识系列- 13 常见类库介绍(二)日期时间类

    0. 前言 上一篇内容介绍了Console类和Math类,这篇内容着重介绍一下C#中时间日期的处理方式. 上一篇勘误: 上一篇中关于静态类没有构造函数,这一表述有误.正确的说法是C#中静态类不包含常规 ...

  5. [C# 基础知识系列]专题八: 深入理解泛型(二)

    引言: 本专题主要是承接上一个专题要继续介绍泛型的其他内容,这里就不多说了,就直接进入本专题的内容的. 一.类型推断 在我们写泛型代码的时候经常有大量的"<"和"& ...

  6. C# 基础知识系列- 3 集合数组

    简单的介绍一下集合,通俗来讲就是用来保管多个数据的方案.比如说我们是一个公司的仓库管理,公司有一堆货物需要管理,有同类的,有不同类的,总而言之就是很多.很乱.我们对照集合的概念对仓库进行管理的话,那么 ...

  7. C# 基础知识系列-13 常见类库(三)

    0. 前言 在<C# 基础知识系列- 13 常见类库(二)>中,我们介绍了一下DateTime和TimeSpan这两个结构体的内容,也就是C#中日期时间的简单操作.本篇将介绍Guid和Nu ...

  8. C# 基础知识系列- 14 IO篇 文件的操作 (3)

    本篇继续前两篇内容,跟大家介绍一下Path类以及FileSystemInfo这个类的主要方法和属性. 上文提到,在<C# 基础知识系列-IO篇>之文件相关的内容完结之后,会带领大家开发一个 ...

  9. C# 基础知识系列- 14 IO篇 流的使用

    0. 前言 继续之前的C# IO流,在前几篇小短片中我们大概看了下C# 的基础IO也对文件.目录和路径的操作有了一定的了解.这一篇开始,给大家演示一下流的各种操作.以文件流为例,一起来看看如何操作吧. ...

随机推荐

  1. JavaScript 原型与继承

    JavaScript 原型与继承 JavaScript 中函数原型是实现继承的基础.prototype.construct.原型链以及基于原型链的继承是面向对象的重要内容 prototype 原型即 ...

  2. OO课程的完结,软件工程学习的开始

    目录 UML小结 阅读学习 大象:Thinking in UML UML精粹 UML和模式应用 本单元作业的架构设计 四个单元中架构设计及OO方法的演进 四个单元中测试与实践的演进 课程收获 三个具体 ...

  3. 扩展gRPC支持consul服务发现和Polly策略

    gRPC由于需要用工具生成代码实现,可开发性不是很高,在扩展这方面不是很友好 最近研究了下,进行了扩展,不需要额外的工具生成,直接使用默认Grpc.Tools生成的代理类即可 相关源码在文章底部 客户 ...

  4. thinkPHP渗透之经验决定成败

    如上图,目标就一个登陆框,最近 Thinkphp 程序很多,根据后台地址结构,猜测可能是 ThinkPHP ,随手输入 xxx 得到 thinkPHP 报错页面,确定目标程序和版本. 然后上 5.X ...

  5. MassDNS:跨域DNS枚举工具

    MassDNS:跨域DNS枚举工具 simeon 原文地址:http://offsecbyautomation.com/Use-MassDNS/ 工具地址:https://github.com/ble ...

  6. Django CBV加装饰器、Django中间件、auth模块

    一. CBV加装饰器 在视图层中,基于函数的视图叫FBV(function base views),基于类的视图叫CBV(class base views).当需要用到装饰器时,例如之前的基于Cook ...

  7. Java 访问修饰符大全详解

    鉴于笔试面试总会遇到,决心仔细认真梳理一下: 1:涉及的关键字:public,default(表示缺省),protected,private,static,final,abstract. 2:关键字含 ...

  8. macro

    Hello, 宏定义魔法世界 宏只是在预处理器里进行文本替换,没有类型,不做任何类型检查,编译器可以对相同的字符串进行优化.只保存一份到 .rodata 段.甚至有相同后缀的字符串也可以优化,你可以用 ...

  9. 模块 psutil 系统信息获取

    psutil模块介绍 psutil是一个开源切跨平台的库,其提供了便利的函数用来获取才做系统的信息,比如CPU,内存,磁盘,网络等.此外,psutil还可以用来进行进程管理,包括判断进程是否存在.获取 ...

  10. WiX 自定义

    WiX 允许用户做一些自定义操作 用户界面向导 对于安装界面,用户可以用自己的位图.图标和许可证文本替换默认的.它们的路径存储在变量中,您可以在命令行或直接在源代码中指定这些变量: <WixVa ...