作为做了快五年的C#开发程序员,有必要思考一下如何提升自己的能力。我认为提升能力的维度就两个(代码可读性高、执行效率高),以下是提高C#编程水平的48个要点,我再每一个要点详细展开加入个人的理解。
可读性高、扩展性强。
readonly为运行时常量,程序运行时进行赋值,赋值完成后便无法更改,因此也有人称其为只读变量。
const为编译时常量,程序编译时将对常量值进行解析,并将所有常量引用替换为相应值。
因为强制类型转换有可能会因为某个条件下转换失败,而使用 as 操作符,转换失败的结果则为null,可以避免程序报错,并能够进行判断进行对应的操作。
使用Conditional属性可以比使用#if/#endif生成更高效的IL代码。在专门针对函数时,它更有优势,它会强制你在条件代码上使用更好的结构。编译器使用Conditional属性来帮助你避免因使用#if/#endif而产生的常见的错误。条件属性比起预处理,它为你区分条件代码提供了更好的支持。
System.Object.ToString()恐怕是.NET中最常用的方法了。自定义类在ToString时,返回的结果并非是我们想要的,因此我们在自定义类重载ToString方法,让自定义类在ToString的时候返回其有作用的值。示例如下:
public class Customer
{
private string Name { get; set; }
private string Phone { get; set; }
public override string ToString()
{
return Name;
}
}
调用ToString方法时,返回名称
个人认为最大的区别就是分配在堆栈的问题。
详情:https://blog.csdn.net/qq_59943770/article/details/120802499
这个我不太懂是什么意思。
主要是为了避免不必要的错误,如enum枚举类型,不从0开始定义的话有时候会造成意想不到的错误。
正确:
public enum ERROR_CODE
{
NO_ERROR = 0,
INVALID_FILE_NAME = 1001,
CANT_BE_ACCESS = 1002,
}
错误:
public enum ERROR_CODE
{
INVALID_FILE_NAME = 1001,
CANT_BE_ACCESS = 1002,
}
简单来说:
ReferenceEquals:即Object.ReferenceEquals(param1,param2),是用于判断两个对象ID是否相等。
Equals:即Object.Equals(),静态的Equals()是使用左边参数实例的Equals()方法来断定两个对象是否相等。
==:即用于判断两个值类型的内容是否相等。
效率低
1.写法简单
2.不需要通过索引获取容器中的元素
为了更好的作为判断、避免不必要的错误,如Main方法中定义变量:
public class A
{
public void Main()
{
private B b = new B();
private string str = "";
private string str = null;
}
}
public class B
{
public string Str {get;set;}
}
总的来说,这样的写法的好处就是可读性高、出错率小。如:
public class MySingleton
{
private static readonly MySingleton _theOneAndOnly;
static MySingleton()
{
_theOneAndOnly = new MySingleton();
}
public static MySingleton TheOnly
{
get{ return _theOneAndOnly; }
}
///
/// 避免从外部创建对象的私有构造函数
///
private MySingleton()
{}
}
这样的做法就是让一个接受参数最多的构造函数做"主构造函数",且在主构造函数中实现必须的业务逻辑,其余的构造函数只要使用this关键字把传入的参数转发给主构造函数,并且提供必须的其它参数,这样子我们整个类中需要我们操心的就是那个主构造函数了,其余构造函数基本上可以为空。
:this()/:this(params)是继承构造函数
public class Person
{
public string personName;
//定义年龄为可空类型,这样就可以赋予其null值
public int personAge;
//下面前三个构造函数都是去调用参数最多的第四个构造函数,只取它们所需要的部分参数即可
//这样的做法就是this串联构造函数
public Person():this("",0)
{}
public Person(string name):this("evan",null)
{ }
public Person(int age):this("",20)
{ }
public Person(string name, int? age)
{
this.personName = name;
//通过判断传入的age是否null值
//如果属于null值,则赋值100
this.personAge = age;
}
public void Display()
{
Console.WriteLine("Name:{0},Age:{1}\n", personName, personAge);
}
}
主函数调用如下:
static void Main(string[] args)
{
Person per1 = new Person();
per1.Display();
Person per2 = new Person(20);
per2.Display();
Person per3 = new Person("evan");
per3.Display();
Person per4 = new Person("evan", 20);
per4.Display();
Console.ReadLine();
}
这个比较容易理解,使用using和try/finally,当里面的代码执行完后,则会释放资源,这是性能上的调优。
小知识:using实质在程序编译阶段,编译器会自动将using语句生成为try-finally语句,并在finally块中调用对象的Dispose方法,来清理资源。 所以,using语句等效于try-finally语句。
意思是尽量少的new对象(能全局使用就不局部多次new对象使用),因为每次new对象都会占用堆的资源并产生垃圾,GC机制在释放并回收资源是需要消耗CPU,而当需要释放更多的堆栈内存并回收时,则需要消耗更多的CPU。
原因有两个,主要是关于效率问题。一个就是对于堆的操作效率比较低;另一个就是对于堆上分配的内存资源,需要GC来回收,从而降低程序效率。
总结:资源分为托管资源(由CLR管理,也就是我们new出来的对象)、非托管资源(Windows内核对象、文件操作、数据库连接、socket、网络等)。实现类的Dispose方法,可以有效、及时的释放资源,更好的利用资源。
详情请看https://zhuanlan.zhihu.com/p/244894004
接口是一种约束,优先使用接口的好处在于可以便于管理、调用,而且接口是可以多继承的。
接口:是对继承类的约束、规范。
重载:是同一个方法名,但不同参数。
通过定义委托,并规定参数个数、参数类型,方便在回调函数实现业务逻辑。
不太理解。