最近涌入了一批初学C#的PLC工程师们,有很多人想知道C#有哪些快捷键。今天这篇文章不仅告诉你有哪些快捷键,还会告诉你怎么做自己的快捷键。
每个C#初学者都应该经历过这样的情形:一次偶然的机会,看到别人只输入prop,然后就快速地写出了完整的属性代码,感到很神奇。然后,我们厚着脸皮问别人,别人会告诉你,输入prop,接着连续按两个Tab,就可以实现,你尝试了,发现确实好用。
在后面的学习过程中,我们慢慢发现for、foreach、switch也都有类似的功能。
然后,可能你就会想,究竟有多少这种快捷语法呢?
你可能也只是想想而已,没有太去深究,直到遇到了我们,今天咱们就把这个事儿弄明白。
一、揭开面纱
我们打开Visual Studio,创建一个简单的控制台项目,然后在菜单栏中的工具中,找到代码片段管理器,语言我们选择CSharp,然后选择Visual C#,我们看到了这些东西:
我们似乎有点明白了,这些快捷代码有个专业术语叫做代码片段,英文名称CodeSnippet。我们看到了我们熟悉的prop、propfull、switch,也看到了一些我们不太熟悉的面孔:ctor、propg、iterindex、interator,总共大概有40个左右,下面我们对一些目前开发中,常用的CodeSnippet做一下说明:
1、#region:代码折叠器
#region MyRegion #endregion
2、ctor:构造方法
public Program () { }
3、class:类
class MyClass { }
4、cw:控制台输出
Console.WriteLine();
5、do:do-while循环
do { } while (true);
6、for:for循环
for (int i = 0; i < length; i++) { }
7、foreach:foreach循环
foreach (var item in collection) { }
8、forr:for逆循环
for (int i = length - 1; i >= 0; i--) { }
9、lock:锁
lock (this) { }
10、mbox:messagebox.show
System.Windows.Forms.MessageBox.Show("Test");
11、prop:简化属性
public int MyProperty { get; set; }
12、propfull:完整属性
private int myVar; public int MyProperty { get { return myVar; } set { myVar = value; } }
13、switch:switch-case
switch (switch_on) { default: }
14、try:异常捕获
try { } catch (Exception) { throw; }
15、tryf:带finally的异常捕获
try { } finally { }
16、using:using
using (resource) { }
17、while:while循环
while (true) { }
二、探索原理
我们继续研究,看下Code Snippet是怎么实现的。
其实Code Snippet只是一个 文件,只不过包含了一些只有 Visual Studio 才认识的元素,这些元素就定义了如何去替我们补全代码,我们仍然通过菜单栏中的工具中,找到代码片段管理器,语言我们选择CSharp,然后选择Visual C#,在上面的这个图中,我们看到了位置这一栏,它指向的是一个文件路径。
1、我们打开这个文件对应的文件夹,发现其实每个快捷代码都对应一个文件。
2、我们打开一个比较熟悉的for循环对应的文件——for.snippet,默认会用Visual Studio打开,我们可以看到使用的是xml文件的格式,全部展开如下图所示:
3、整个snippet文件由2个节点组成,分别是Header和Snippet,其中Header主要是一个声明;Snippet包含具体代码的形式和内容。
4、Header部分主要包含标题、快捷键、说明、作者和Snippet类型相关信息。
Snippet类型分为 Expansion、SurroundsWith 及 Refactoring(只能在重构过程中使用)。
Expansion:允许将代码段插入到光标处。
SurroundsWith:允许将此代码段放置在一段选定的代码周围。比如我们写完一段代码后,发现忘记加 try...catch... 了,这个时候可以选中需要包裹在 try...catch... 中的代码,然后调用 Code Snippet。
5、Snippet部分是重点内容,从结构上来看,主要包括Declarations和Code两个部分,Declarations,顾名思义就是声明变量,而Code就是核心代码,Code中会应用到Declarations中声明的一些变量。这个有点像早期西门子S7-300PLC的SCL语言,需要先定义变量,然后后面才能用。
三、扩展练习一
当我们已经知道Snippet的原理之后,我们就可以制作自己的Code Snippet了。
大家可能发现了,自带的关于异常捕获的有try和tryf两个,但是这两个都无法表示try-catch-finally的逻辑,所以,我们可以先做一个try-catch-finally的Code Snippet。
1、建议还是使用复制-修改的方式来做,我们从Snippets路径中将try.snippet文件拷贝到桌面上,然后修改如下:
2、修改好之后,直接保存并重命名为trycf.snippet
3、复制该文件到Snippets路径中
4、测试结果:在代码编辑器中 CTRL+KL+S,就可以呼出 snippet,我们可以看到有trycf了。
四、扩展练习二
我们在实际开发中,如果发现有代码是经常要写的,我们不希望每次都从头去写,那就可以使用Snippet,这里以串口通信库为例:
public class SerialBase { #region 对象或属性 /// <summary> /// 定义SerialPort对象 /// </summary> private SerialPort MyCom; /// <summary> /// 读取超时时间 /// </summary> public int ReadTimeOut { get; set; } = 2000; /// <summary> /// 写入超时时间 /// </summary> public int WriteTimeOut { get; set; } = 2000; private bool dtrEnable; /// <summary> /// Dtr使能标志 /// </summary> public bool DtrEnable { get { return dtrEnable; } set { this.MyCom.DtrEnable = value; dtrEnable = value; } } private bool rtsEnable; /// <summary> /// Rts使能标志 /// </summary> public bool RtsEnable { get { return rtsEnable; } set { this.MyCom.RtsEnable = value; rtsEnable = value; } } #endregion #region 打开关闭串口 /// <summary> /// 打开串口 /// </summary> /// <param name="iBaudRate">波特率</param> /// <param name="iPortName">串口号</param> /// <param name="iDataBits">数据位</param> /// <param name="iParity">校验位</param> /// <param name="iStopBits">停止位</param> /// <returns>是否成功</returns> public bool Connect(int iBaudRate, string iPortName, int iDataBits, Parity iParity, StopBits iStopBits) { //串口通信对象实例化 MyCom = new SerialPort(iPortName, iBaudRate, iParity, iDataBits, iStopBits); //如果当前串口是打开的,先关闭一下 if (MyCom.IsOpen) { MyCom.Close(); } //设置超时时间 MyCom.ReadTimeout = this.ReadTimeOut; MyCom.WriteTimeout = this.WriteTimeOut; try { //打开串口 MyCom.Open(); } catch (Exception) { return false; } return true; } /// <summary> /// 关闭串口 /// </summary> public void DisConnect() { if (MyCom.IsOpen) { MyCom.Close(); } } #endregion }
1、对于串口通信来说,我们可能每次都要编写这些代码,那么我们能不能把这些代码封装成一个Snippet呢?
2、建议仍然采用复制-修改的方式来做,我们从Snippets路径中将tryf.snippet文件拷贝到桌面上,然后修改如下:
3、重命名为serial.snippet,并复制到Snippets文件夹中。
4、测试结果如下: