一、 使用readonly而不是const

const是编译时常量,readonly是运行时常量。如果引用了一个库中的const常量,则在更新了程序集,但应用程序没有重新编译时,运行结果会出错

如程序集assembly.dll中有如下声明

 public static readonly int Start = ;
public const int End = ;

在ConsoleApp.exe中调用。在正常编译的情况下是没有问题的,但如果更新了assembly.dll中的声明,却不重新编译ConsoleApp.exe,此时End常量的值依旧是10

 public static readonly int Start = ;
public const int End = ;

二、使用is和as关键字,而不是使用强制类型转换

强制类型转换不当会引发 InvalidCastException异常。使用is和as可以避免这个问题

三、使用$ - 字符串内插来格式化字符串,而不是string.Format()函数.这个功能需要C#6.0

https://docs.microsoft.com/zh-cn/dotnet/csharp/language-reference/tokens/interpolated

四、尽量使用Conditional特性,减少#if和#endif的使用

平常我们会使用#if和#endif来执行一些Debug环境下执行的代码。这些代码在编译成Release版本时不会执行,但仍然会有一些开销。这时我们就可以使用Conditional特性,使用了Conditional特性的函数只有在某些环境或者设置了某个值之后才能编译成类的一部分,这样就可以减少Release版本的开销。值得注意的,使用Conditional特性必须把以前的调试部分代码封装成函数才行。

需要了解ConditionalAttribute更详细的说明,可以查看MSDN文档 https://docs.microsoft.com/zh-cn/dotnet/api/system.diagnostics.conditionalattribute?redirectedfrom=MSDN&view=netframework-4.8

使用#if和#endif的情况

当定义了DEBUG符号时,控制台会输出Debug和Release。未定义DEBUG符号时,只会输出Release。

 #define DEBUG

 using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace ConsoleApp5
{
class Program
{
static void Main(string[] args)
{
#if DEBUG
Console.WriteLine("Debug");
#endif
Console.WriteLine("Release"); } }
}

使用Conditional特性的情况

输出情况是跟上面一致的。但当未定义DEBUG符号时,DebugMethod不会被编译进MSIL。可以节省开销

值得注意的是,应用了Conditional特性的函数,返回类型只能为void

 #define DEBUG

 using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace ConsoleApp5
{
class Program
{
static void Main(string[] args)
{
DebugMethod(); Console.WriteLine("Release");
} [Conditional("DEBUG")]
static void DebugMethod()
{
Console.WriteLine("Debug");
} }
}

五、如何正确的对成员变量进行初始化(这个问题困扰了我好久,今天终于有解决方案了)

大多情况下,使用成员初始化器对成员进行初始化。

就是在声明时就进行初始化,而不是放到构造函数。初始化器可以看做是构造函数中初始化语句的另一种表示。初始化器生成的代码会在构造函数前执行。如果是派生类,初始化器会在父类的构造函数前执行,然后再执行子类的构造函数。

public class Patient
{
List<Bitmap> images = new List<Bitmap>();
string patientName;
int patientId; public Patient()
{ }
}

下面三种情况,不推荐使用初始化器语法

1、值类型初始值设为0,引用类型初始值设为null的情况

系统默认的初始化工作将在所有代码执行之前把一切都设置成0或null。系统生成0或者null的这一步操作是位于很底层的实现,会直接使用CPU指令将一整块内存设置为0。

所以以下代码是多余的

 int num = ;
Student stu = null;

2、需要对这个变量执行不同的初始化方式的情况。初始化器语法的前提是,所有的构造函数都会将变量设置为同样的值。

3、在进行初始化时,可能会引发异常的情况。这种情况下,就需要在构造函数中进行初始化,以便进行相应处理。

六、区分值类型和引用类型

值类型应该是那些小型、轻量级的类型,分配在栈上

引用类型则用来构成类层次结构,分配在堆上。

有如下代码

 MyType[] arrayOfTypes = new MyType[];

如果MyType属于值类型,那么将一次分配大小为MyType的100倍空间

如果MyType属于引用类型,那么也仅会分配一次,数组中的每个元素都为空。在初始化数组中的元素时,将执行101次分配,101次分配要比1次分配更占用时间,分配大量的引用 类型将让堆上充满碎片。

还有一点值得注意的是,在集合中查找元素时,如果集合里是值类型,则查找出来的元素跟集合中的元素是不同的引用。如果是引用类型,则查找出来的元素跟集合中的该元素是相同的引用。在修改值的时候,会导致意外的发生。

有如下代码

 class Program
{
static void Main(string[] args)
{
Test1 test1 = new Test1() { Name = "Test1"};
Test2 test2 = new Test2() { Name = "Test2"}; List<Test1> list1 = new List<Test1>() { test1 };
var temp1 = list1.Find(x => x.Name == "Test1");
Console.WriteLine(object.ReferenceEquals(test1,temp1)); temp1.Name = "Modified Test1";
Console.WriteLine(list1.ElementAt().Name); List<Test2> list2 = new List<Test2>() { test2 };
var temp2 = list2.Find(x => x.Name == "Test2");
Console.WriteLine(object.ReferenceEquals(test2,temp2)); temp2.Name = "Modified Test2";
Console.WriteLine(list2.ElementAt().Name); }
} struct Test1
{
public string Name { get; set; }
} class Test2
{
public string Name { get; set; }
}

运行结果如下

可以看到,查找出来的值类型集合中的元素,跟添加时的元素并不是同一个引用,而且修改值,也不会导致集合中元素的更改。

引用类型则相反。

C#高效编程的更多相关文章

  1. C# 高效编程笔记2

    C# 高效编程笔记2 1.理解GetHashCode()的陷阱 (1)作用:作为基于散列集合定义键的散列值,如:HashSet<T>,Dictionary<K,V>容器等 (2 ...

  2. C# 高效编程笔记1

    C# 高效编程笔记1 1.使用属性而不是可访问的数据成员 (1).NET Framework中的数据绑定类仅支持属性,而不支持共有数据成员 (2)属性相比数据成员更容易修改 2.用运行时常量(read ...

  3. Python高效编程的19个技巧

    初识Python语言,觉得python满足了我上学时候对编程语言的所有要求.python语言的高效编程技巧让我们这些大学曾经苦逼学了四年c或者c++的人,兴奋的不行不行的,终于解脱了.高级语言,如果做 ...

  4. 架构师速成-如何高效编程 for java

    引子 赵云大喝一声,挺枪骤马杀入重围,左冲右突,如入无人之境.那枪浑身上下,若舞梨花:遍体纷纷,如飘瑞雪. 赵云是所有历史人物中我最喜欢的一个,如果放到现代,他走了it的道路,一定可以成为一个编程高手 ...

  5. C语言高效编程的几招(绝对实用,绝对经典)

    编写高效简洁的C语言代码,是许多软件工程师追求的目标.废话不说,走起! 第一招:以空间换时间 计算机程序中最大的矛盾是空间和时间的矛盾,那么,从这个角度出发逆向思维来考虑程序的效率问题 eg.字符串的 ...

  6. [收藏转贴]struct探索·extern "C"含义探索 ·C++与C的混合编程·C 语言高效编程的几招

    一.C/C++语言 struct深层探索 1.自然对界 struct是一种复合数据类型,其构成元素既可以是基本数据类型(如 int.long.float等)的变量,也可以是一些复合数据类型(如 arr ...

  7. [.NET] 《C# 高效编程》(一) - C# 语言习惯

    C# 语言习惯 目录 一.使用属性而不是可访问的数据成员 二.使用运行时常量(readonly)而不是编译时常量(const) 三.推荐使用 is 或 as 操作符而不是强制类型转换 四.使用 Con ...

  8. [.NET] 《Effective C#》快速笔记 - C# 高效编程要点补充

    <Effective C#>快速笔记 - C# 高效编程要点补充 目录 四十五.尽量减少装箱拆箱 四十六.为应用程序创建专门的异常类 四十七.使用强异常安全保证 四十八.尽量使用安全的代码 ...

  9. 【Matlab编程】Matlab高效编程技巧

    1.默认状态下,matlab显示精度是short型,而默认的计算精度是double型,并且显示精度与计算精度没有关系. 2. 一只失明的猫的问题:注意方法! 3.给数组预分配空间是基本的高效编程准则之 ...

  10. 18个Python高效编程技巧,Mark!

    初识Python语言,觉得python满足了我上学时候对编程语言的所有要求.python语言的高效编程技巧让我们这些大学曾经苦逼学了四年c或者c++的人,兴奋的不行不行的,终于解脱了.高级语言,如果做 ...

随机推荐

  1. 实现mysql的读写分离(mysql-proxy)____1(mysql的主从复制,基于gtid的主从复制,半同步复制,组复制)

    主从复制原理: 从库生成两个线程,一个I/O线程,一个SQL线程: i/o线程去请求主库 的binlog,并将得到的binlog日志写到relay log(中继日志) 文件中:主库会生成一个 log ...

  2. sentinel-dashboard安装、运行(docker)

    https://github.com/alibaba/Sentinel/releases 下载源码 修改成支持nacos(略) mkdir /opt/sentinel-dashboard把编译好的se ...

  3. vue-cli安装webpack项目及初始配置

    这个下载包是自己基于 webpack 搞的,可以看看https://github.com/chichengyu/webpack vue-cli安装 输入 npm install vue-cli -g ...

  4. Presto: SQL on Everything

    Presto是FB开源出来的实时分析引擎,可以federated的从多种数据源去读取数据,做联合查询,支持实时Interactive BI或bath ETL的需求 从其问题域来看,基本是和spark是 ...

  5. hinkphp项目部署到Linux服务器上报错“模板不存在”如何解决

    检查了服务器上的文件,并没有缺少文件,再次上传文件到服务器,还是报错.莫名其妙,怀疑是代码问题. 仔细检查后,发现是模板的文件名问题: 用过TP的都知道:thinkphp会在$this->dis ...

  6. Ubuntu 安装最新版 (1.12) Golang 并使用 go mod

    wget https://dl.google.com/go/go1.12.4.linux-amd64.tar.gz sudo tar -zxvf go1.12.4.linux-amd64.tar.gz ...

  7. easyui datagrid的editor编辑器如何为validatebox控件添加改变事件

    项目中需要为行编辑器Editor的某个列的文本框添加改变事件 需求:新增行时,为用户名输入特殊字符进行验证,不允许保存用户数据 html页面 <table id="gridlist&q ...

  8. 目前流行前端几大UI框架排行榜

    在前端项目开发过程中,总是会引入一些UI框架,已为方便自己的使用,很多大公司都有自己的一套UI框架,下面就是最近经常使用并且很流行的UI框架. 一.Mint UI 流行指数:★★★★ Mint UI是 ...

  9. NVM 安装注意

    windows 系统下尽量使用安装版本,选择安装路径时,路径中不能带有空格,否则无法使用 nvm use xx.xx.xx

  10. python2 pickle.dump生成的文件,python3 pickle.load怎么加载

    会报错: UnicodeDecodeError: 'ascii' codec can't decode byte 0xa0 in position 3: ordinal not in range(12 ...