C#规范整理·语言要素

如有不理解,请留言,开始!

640?wx_fmt=png

1. 正确操作字符串

  • 拼接字符串一定要考虑使用 StringBuilder ,默认长度为16,实际看情况设置。

  • StringBuilder本质: 是以非托管方式分配内存。

  • 同时StringFormat方法 内部也是使用StringBuilder进行字符串格式化。

2. 使用默认转型方法

  1. 类型的转换运算符 :每个类型内部都有一个方法(运算符),分为隐式转换和显示转换。
    自己实现隐式转换:

puclic static implicit operator Ip(string ip) 
{
Ip iptemp=new Ip(ip);
return iptemp;
}
  1. 使用类型内置的Parse、TryParse、 ToString、ToDouble、 ToDateTime

  2. 使用帮助类提供的方法: System.Convert类、 System.BitConverter类来进行类型的转换。

  3. 使用CLR支持的类型:父类和子类之间的转换。

3. 区别对待强制转型与as和is

为了编译更强壮的代码,建议更常使用as和is

什么时候使用as

  • 如果类型之间都上溯到了某个共同的基类,那么根据此基类进行的转型(即基类转型为子类本身)应该使用as。子类与子类之间的转型,则应该提供转换操作符,以便进行强制转型。
    as操作符永远不会抛出异常,如果类型不匹配(被转换对象的运行时类型既不是所转换的目标类型,也不是其派生类型),或者转型的源对象为null,那么转型之后的值也为null。

什么时候使用is

  • as操作符有一个问题,即它不能操作基元类型。如果涉及基元类型的算法,就需要通过is转型前的类型来进行判断,以避免转型失败。

4.TryParse比Parse好

这个肯定好,不说了。安全

5.使用int?来确保值类型也可以为null

基元类型为什么需要为null?考虑两个场景:

  1. 数据库支持整数可为空

  2. 数据在传输过程中存在丢失问题,导致传过来的值为null

写法: int?i=null;

语法T?是Nullable<T>的简写,两者可以相互转换。可以为null的类型表示其基础值类型正常范围内的值再加上一个null值。例如,Nullable<Int32>,其值的范围为-2 147 483 648~2 147 483 647,再加上一个null值。

?经常和??配合使用,比如:

Copy

int?i=123;
int j=i??0;

6.区别readonly和const的使用方法

使用const的理由只有一个,那就是效率。之所以说const变量的效率高,是因为经过编译器编译后,我们在代码中引用const变量的地方会用const变量所对应的实际值来代替。比如: const=100, const和100被使用的时候是等价,const自带static光圈。
const和readonly的本质区别如下:

  1. const是编译期常量,readonly是运行期常量

  2. const只能修饰基元类型、枚举类型或字符串类型,readonly没有限制。

  • 注意:在构造方法内,可以多次对readonly赋值。即在初始化的时候。

7.将0值作为枚举的默认值

允许使用的枚举类型有byte、sbyte、short、ushort、int、uint、long和ulong。应该始终将0值作为枚举类型的默认值。不过,这样做不是因为允许使用的枚举类型在声明时的默认值是0值,而是有工程上的意义。
既然枚举类型从0开始,这样可以避免一个星期多出来一个0值。

8.避免给枚举类型的元素提供显式的值

不要给枚举设定值。有时候有某些增加的需要,会为枚举添加元素,在这个时候,就像我们为枚举增加元素ValueTemp一样,极有可能会一不小心增加一个无效值。

9.习惯重载运算符

比如:Salary familyIncome=mikeIncome+roseIncome; 阅读一目了然。通过使用opera-tor关键字定义静态成员函数来重载运算符,让开发人员可以像使用内置基元类型一样使用该类型。

10.创建对象时需要考虑是否实现比较器

有特殊需要比较的时候就考虑。集合排序比较通过linq 也可以解决。

11.区别对待==和Equals

无论是操作符“==”还是方法“Equals”,都倾向于表达这样一个原则:

  1. 对于值类型,如果类型的值相等,就应该返回True。

  2. 对于引用类型,如果类型指向同一个对象,则返回True。

    注意 

  • 由于操作符“==”和“Equals”方法从语法实现上来说,都可以被重载为表示“值相等性”和“引用相等性”。所以,为了明确有一种方法肯定比较的是“引用相等性”,FCL中提供了Object.ReferenceEquals方法。该方法比较的是:两个示例是否是同一个示例。

  • 对于string这样一个特殊的引用类型,微软觉得它的现实意义更接近于值类型,所以,在FCL中,string的比较被重载为针对“类型的值”的比较,而不是针对“引用本身”的比较。

12.重写Equals时也要重写GetHashCode

  • 除非考虑到自定义类型会被用作基于散列的集合的键值;否则,不建议重写Equals方法,因为这会带来一系列的问题。
    集合找到值的时候本质上是先去 查找HashCode,然后才查找该对象来比较Equals

注意
重写Equals方法的同时,也应该实现一个类型安全的接口IEquatable<T>,比如 :class Person:IEquatable

13.为类型输出格式化字符串

有两种方法可以为类型提供格式化的字符串输出。

  1. 一种是意识到类型会产生格式化字符串输出,于是让类型继承接口IFormattable。这对类型来说,是一种主动实现的方式,要求开发者可以预见类型在格式化方面的要求。

  2. 更多的时候,类型的使用者需为类型自定义格式化器,这就是第二种方法,也是最灵活多变的方法,可以根据需求的变化为类型提供多个格式化器。

一个典型的格式化器应该继承接口IFormatProvider和ICustomFomatter

14.正确实现浅拷贝和深拷贝

浅拷贝 

将对象中的所有字段复制到新的对象(副本)中。其中,值类型字段的值被复制到副本中后,在副本中的修改不会影响到源对象对应的值。而引用类型的字段被复制到副本中的是引用类型的引用,而不是引用的对象,在副本中对引用类型的字段值做修改会影响到源对象本身。

深拷贝 

同样,将对象中的所有字段复制到新的对象中。不过,无论是对象的值类型字段,还是引用类型字段,都会被重新创建并赋值,对于副本的修改,不会影响到源对象本身。

无论是浅拷贝还是深拷贝,微软都建议用类型继承IClone-able接口的方式明确告诉调用者:该类型可以被拷贝。当然,ICloneable接口只提供了一个声明为Clone的方法,我们可以根据需求在Clone方法内实现浅拷贝或深拷贝。

  • 一个简单的浅拷贝的实现代码如下所示:

Copy

class Employee:ICloneable
{
public string IDCode {get;set;}
public int Age {get;set; }
public Department Department{get;set;}

#region ICloneable成员
public object Clone()
{
return this.MemberwiseClone();
}

#endregion

}

class Department
{
public string Name {get;set;}
public override string ToString()
{
return this.Name;
}
}

注意到Employee的IDCode属性是string类型。理论上string类型是引用类型,但是由于该引用类型的特殊性(无论是实现还是语义),Object.MemberwiseClone方法仍旧为其创建了副本。也就是说,在浅拷贝过程,我们应该将字符串看成是值类型。

  • 一个简单的深拷贝实现样例如下(建议使用序列化的形式来进行深拷贝)

Copy

class Employee:ICloneable
{
public string IDCode{get;set;}
public int Age{get;set;}
public Department Department{get;set;}

#region ICloneable成员
public object Clone()
{
using(Stream objectStream=new MemoryStream())
{
IFormatter formatter=new BinaryFormatter();
formatter.Serialize(objectStream,this);
objectStream.Seek(0,SeekOrigin.Begin);
return formatter.Deserialize(objectStream)as Employee;
}
}
#endregion}

同时实现深拷贝和浅拷贝

由于接口ICloneable只有一个模棱两可的Clone方法,所以,如果要在一个类中同时实现深拷贝和浅拷贝,只能由我们自己实现两个额外的方法,声明为DeepClone和Shallow。Em-ployee的最终版本看起来应该像如下的形式:

Copy

[Serializable]
class Employee:ICloneable
{
public string IDCode{get;set;}
public int Age{get;set;}
public Department Department{get;set;}
#region ICloneable成员
public object Clone()
{
return this.MemberwiseClone();
}

#endregion
public Employee DeepClone()
{
using(Stream objectStream=new MemoryStream())
{
IFormatter formatter=new BinaryFormatter();
formatter.Serialize(objectStream,this);
objectStream.Seek(0,SeekOrigin.Begin);
return formatter.Deserialize(objectStream)as Employee;
}
}

public Employee ShallowClone()
{
return Clone()as Employee;
}}

14.利用dynamic来简化反射实现

dynamic是Framework 4.0的新特性。dynamic的出现让C#具有了弱语言类型的特性。编译器在编译的时候不再对类型进行检查,编译器默认dynamic对象支持开发者想要的任何特性。
比如,即使你对GetDynamicObject方法返回的对象一无所知,也可以像如下这样进行代码的调用,编译器不会报错:

Copy

dynamic dynamicObject=GetDynamicObject();
Console.WriteLine(dynamicObject.Name);
Console.WriteLine(dynamicObject.SampleMethod());

当然,如果运行时dynamicObject不包含指定的这些特性(如上文中带返回值的方法SampleMethod),运行时程序会抛出一个RuntimeBinderException异常:“System.Dynamic.ExpandoObject”未包含“Sam-pleMethod”的定义。

var与dynamic有巨大的区别

  • var是编译器的语法糖

  • dynamic是运行时解析,在编译期时,编译器不对其做任何检查。

反射使用

  • 不使用dynamic方式

Copy

DynamicSample dynamicSample=new DynamicSample();
var addMethod=typeof(DynamicSample).GetMethod("Add");
int re=(int)addMethod.Invoke(dynamicSample,new object[] {1,2});
  • 使用dynamic方式

Copy

dynamic dynamicSample2=new DynamicSample();
int re2=dynamicSample2.Add(1,2);

建议:始终使用dynamic来简化反射实现。

总结

在大部分应用情况下,“效率”并没有那么高的地位,灵活性更重要。在部分情况下,“灵活性”并没有那么高的地位,效率最重要。

原文地址:https://www.cnblogs.com/zhan520g/p/11014918.html

.NET社区新闻,深度好文,欢迎访问公众号文章汇总 http://www.csharpkit.com 
640?wx_fmt=jpeg

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/315417.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

NetCore服务虚拟化01(集群组件Sodao.Core.Grpc)

一. 起始去年.NetCore2.0的发布,公司决定新项目采用.NetCore开发,当作试验。但是问题在于当前公司内部使用的RPC服务为Thrift v0.9 zookeeper版本,经过个性化定制,支持了异步,但也因为如此,这么多年来一直…

CF741D Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths 树启 + 状压

传送门 文章目录题意:思路:题意: 思路: 据说是树启的压轴题。 先观察题意,字符有1−221-221−22中,为什么不是1−261-261−26个?显然他就是让你状压的。我们考虑将每条路径上字符状压成statest…

Codeforces Round #610 (Div. 2) D. Enchanted Artifact 交互 + 思维

传送门 文章目录题意:思路:题意: 思路: 首先我们发现如果知道了字符串的长度,我们就可以O(n1)O(n1)O(n1)次询问求解出来。比如当前长度为nnn,那么我们就可以构造出一个长度为nnn的全′a′a′a′字符串&…

Docker+ Kubernetes已成为云计算的主流(二十六)

前言 最近正在抽时间编写k8s的相关教程,很是费时,等相关内容初步完成后,再和大家分享。对于k8s,还是上云更为简单、稳定并且节省成本,因此我们需要对主流云服务的容器服务进行了解,以便更好地…

P4137 Rmq Problem / mex 主席树求mex

传送门 文章目录题意:思路:题意: 思路: 按照值建线段树,每个位置维护值出现的最后位置,让后可持久化一下,当查询[l,r][l,r][l,r]的时候,我们只需要在[1,r][1,r][1,r]中找最后出现位…

《刷新》:拥抱同理心,建立成长型思维

“ 不刷新即死亡”2018年,很多朋友包括博客园里的很多园友都在阅读微软第三任CEO萨提亚纳德拉的这本《刷新》并且发布了很多读后感,但我却一直没有来得及阅读。刚好最近订阅了喜马拉雅的VIP会员,每天上下班时间开始了听书之旅,这里…

Consul初探-集成ocelot

前言由于 Consul 的高可用性、丰富的API、友好的 Web 控制台界面等特点,Consul 的发展非常迅猛,得益于 .NETCore 社区的快速发展和社区成员的贡献,我们现在可以非常方便快速的将 Consul 集成到 .NETCore 中,在 Ocelot 的集成方面也…

2021年广东工业大学第十五届文远知行杯程序设计竞赛(同步赛) H.有多短 思维

传送门 文章目录题意:思路:题意: 思路: 可以发现树的直径起点和终点一定是两个度数为111的点,所以我们可以把kkk平均的分给所有度数为111的点,这样答案就为2∗kcnt\frac{2*k}{cnt}cnt2∗k​。 证如果分配给…

Identity和IdentityServer的区别及联系

关于Identity和IdentityServer初学的时候可能会有一些疑惑(虽然我也不是很精深吧),但是,这里说一下自己关于这两者的一些理解,如有错误,欢迎指正总体上,ASP.NET Core Identity提供了一个用来管理和存储用户账户的框架.IdentitySer…

C#规范整理·集合和Linq

LINQ(Language Integrated Query,语言集成查询)提供了类似于SQL的语法,能对集合进行遍历、筛选和投影。一旦掌握了LINQ,你就会发现在开发中再也离不开它。  开始!前言C#中的集合表现为数组和若干集合类。不管是数组还…

UVA - 11361 Investigating Div-Sum Property(数位dp/记忆化搜索板子)

题目:https://vjudge.net/problem/UVA-11361 思路:数位dp,用记忆化搜索写,dp[pos][i][j][limit] 代表剩余有pos位,每位上的数字和模k 等于i, 当前总数值模k等于j,limit代表限制位。 本题还要注意…

C#并发编程之异步编程(三)

写在前面本篇是异步编程系列的第三篇,本来计划第三篇的内容是介绍异步编程中常用的几个方法,但是前两篇写出来后,身边的朋友总是会有其他问题,所以决定再续写一篇,作为异步编程(一)和异步编程(二)的补充。本篇内容主要…

UVA - 10253 Series-Parallel Networks(递推式、记忆化搜索写法)

题目:UVA-10253 题目翻译(来自蓝书): 串并联网络有两个端点,一个叫源,一个叫汇,递归定义如下: (1) 一条单独的边是串并联网络。 (2)…

C#规范整理·泛型委托事件

基于泛型,我们得以将类型参数化,以便更大范围地进行代码复用。同时,它减少了泛型类及泛型方法中的转型,确保了类型安全。委托本身是一种引用类型,它保存的也是托管堆中对象的引用,只不过这个引用比较特殊&a…

Abp v0.18.0 新版本: MVC Module 启动模板

0.18.0将于近期发布, 本文内容针对于0.18.0版本.MVC模块启动模板可用此模板开发基于模块开发最佳实践和约定的可复用 应用程序模块 . 它同样适用于开发微服务.如何开始?你可以使用ABP CLI创建基于此启动模板的新项目,或者你也可以在入门页面创建并下载项目. 在这里我们使用CLI…

Consul-template+nginx实现自动负载均衡

前言consul-template 是 Consul 的一个守护程序,使用 consul-template 可以方便快速的实现对 Consul Key/Value 存储系统的访问,可以从 KV 系统中读取数据、监视变动、同步本地文件;还可以在执行模板更新的同时,执行本地系统命令&…

Codeforces Round #613 (Div. 2) E. Delete a Segment 离散化

传送门 文章目录题意:思路:题意: 思路: 我们考虑将区间内的位置都111,之后求区间段数就可以转换成求,连续不为000的区间段数,由于范围有[−1e9,1e9][-1e9,1e9][−1e9,1e9]的级别,所…

是时候挥别 SQL Server 2008 了

微软 宣布将于 2019 年 7 月终止对 SQL Server 2008 和 2008 R2 的支持,使用 SQL Server 2008 的公司应该认真开始考虑下一步了。本文引用了一家数字化转型咨询公司高级顾问对此的分析,并提供了一些解决方案和注意事项。如果你还在使用 微软 2008 版的 S…

领域驱动设计,让程序员心中有码(八)

领域驱动是十五年前,由Eric Evans提出的解决软件工程复杂性问题的方法,作者从自己多年软件开发的角度出发,通过引入领域驱动设计的概念以及一系列战略设计模式和战术方法,为混沌的软件开发领域带来了一缕阳光。在过去的许多年&…

H - Great Cells Gym - 101194H(数学推导/思维)

VJ地址 ps:在训练时写这道题 差点被送走了 我们可以发现给出的公式可以转化这样 这个就不说了,就是k^(nm)所以排列的可能; 然后我们要重点观察这个公式,可以发现g * Ag(方案数 * good点的数量) 可以意味这组成一个…