C#学习笔记

1.概念

1. 接口作用

http://blog.jobbole.com/85751/

2. 命名空间

http://blog.csdn.net/beyondqd/article/details/6696936

3. 序列化与反序列化

序列化:将对象状态转换为可保持或传输的格式的过程(保存文件内容);
反序列化:将内容即流转换为对象(读取文件内容);
xml文件的序列化与反序列化的示例:

#config是根据xml的格式定义的一个类,file是xml文件的路径
public static Config LoadConfig(string file)
{
	XmlSerializer xs = new XmlSerializer(typeof(Config));
	StreamReader sr = new StreamReader(file);
	Config config = xs.Deserialize(sr) as Config;
	sr.Close();

	return config;
}

public void SaveConfig(string file)
{
	XmlSerializer xs = new XmlSerializer(typeof(Config));
	StreamWriter sw = new StreamWriter(file);
	xs.Serialize(sw, this);
	sw.Close();
}

4. Invoke BeginInvoke

http://www.cnblogs.com/zhangchenliang/p/4953649.html
从不是创建控件的线程访问控件

this.InvokeRequired 判断当前线程是否是UI线程。
如果this.InvokeRequired = true,你需要通过this.Invoke()传递委托去操作界面。否则直接操作即可。


Control.Invoke 方法 (Delegate) :在拥有此控件的基础窗口句柄的线程上同步执行指定的委托。
Control.BeginInvoke 方法 (Delegate) :在创建控件的基础句柄所在线程上异步执行指定委托。

private void Form1_Load(object sender, EventArgs e)
{
	myThread = new Thread(new ThreadStart(ShowMsg));
	myThread.Start();
}
public void ShowMsg()
{
	showMsg01("message");
}
public void showMsg01(string msg)
{
	//在线程里以安全方式调用控件 
	//receiveMsg01控件的名字	
	if (receiveMsg01.InvokeRequired)
	{
		MyInvoke _myinvoke = new MyInvoke(showMsg01);
		receiveMsg01.Invoke(_myinvoke, new object[] { msg });
	}
	else
	{
		receiveMsg01.AppendText(msg);
	}
} 

5. 委托(delegate)和事件(event)

http://blog.csdn.net/wxfx888/article/details/78079970
http://blog.csdn.net/cgguang/article/details/53103503
https://www.cnblogs.com/yinqixin/p/5056307.html
事件是由一系列动作组成。那么动作是什么呢?动作就是函数,因为函数就是做什么,一个函数就是一个动作,反之亦然。因此,事件是由一系列函数组成的。那么,函数有大有小,把一系列的函数实体加入到事件中,是不明智的。我们就将函数的代表加入到事件中。什么是函数的代表呢?在C#中,有一个delegate 关键词,它就是标记一个函数代表类的。
定义委托时,命名规则是名字 + EventHandler
步骤:
1、创建一个委托;
2、将创建的委托与特定事件关联;
3、编写C#事件处理程序;
4、利用编写的C#事件处理程序生成一个委托实例;
5、把这个委托实例添加到产生事件对象的事件列表中去(+=),这个过程又叫订阅事件。取消的方式是(-=)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
 
namespace Example_EventTest
{
    class JudgeEvent
    { 
        //定义一个委托
        public delegate void delegateClick();
        //定义一个事件
        public event delegateClick eventClick;
        //引发事件的方法
        public void onClick()
        {
            eventClick();//被引发的事件
        } 
    }
    class DoClick
    { 
        //定义事件处理方法
        public void doC()
        {
            Console.WriteLine("鼠标被点击了");
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            DoClickrunsport = new DoClick();//实例化事件发布者
            JudgeEvent JudgeE= new JudgeEvent();//实例化事件订阅者
 
            //订阅事件
            JudgeE.evenClick+=new JudgeE.delegateClick(DoClick.doC);
 
            //引发事件
            JudgeE.onClick();
 
            Console.ReadKey();
        }
    }
}

Action和Func, delegate以及Eventhandler的区别

都是对委托的简写,
delegate是很宽泛的,格式内容都不受限
Action相当于可以带很多参数的无返回值的委托
Func可以带很多参数,但是必须带返回值的委托. Func<T1,T2,T3,T4,TResult>
EventHandler可以带一整个参数列表,无返回值

Action 委托 + lambda 表达式
https://blog.csdn.net/Golden_Shadow/article/details/7206250

6. XML

http://www.cnblogs.com/tomin/archive/2009/02/27/1399566.html

7. 读写配置文件

http://www.cnblogs.com/wayfarer/archive/2004/07/16/24783.html

8. 线程同步

所谓同步:是指在某一时刻只有一个线程可以访问变量。
如果不能确保对变量的访问是同步的,就会产生错误。
c#为同步访问变量提供了一个非常简单的方式,即使用c#语言的关键字Lock,它可以把一段代码定义为互斥段,互斥段在一个时刻内只允许一个线程进入执行,而其他线程必须等待。在c#中,关键字Lock定义如下:
Lock(expression)
{
statement_block
}
expression代表你希望跟踪的对象:
如果你想保护一个类的实例,一般地,你可以使用this;
如果你想保护一个静态变量(如互斥代码段在一个静态方法内部),一般使用类名就可以了
而statement_block就算互斥段的代码,这段代码在一个时刻内只可能被一个线程执行。
以书店卖书为例
http://blog.csdn.net/ermao_zbp/article/details/78293782?locationNum=4&fps=1

9. 互斥锁

互斥锁(lock)
lock 关键字将语句块标记为临界区,方法是获取给定对象的互斥锁,执行语句,然后释放该锁。当任何一个线程获取到锁后,其他线程如果需要使用该临界区内代码,则必须等待前一个线程使用完毕后释放锁。
代码示例:

Object thisLock = new Object();  
lock (thisLock)  
{  
    // 临界区代码块  
}

10. 组件开发

1. 概念

从类继承方向解释,.NET中的组件、控件和用户控件。
其实从字面上已经可以理解各自的不同了。但是具体关系其实是从类的继承上来区别的。一般控件派生于:Control类,所以从此类派生出的称之为控件。一般组件派生于:Component类,所以从此类派生出的称之为组件。

用户控件派生于:UserControl类,所以从该类派生出的称之为用户控件。(我们之所以这么叫其实是因为英文翻译上的习惯)他们之间的关系主要是:UserControl继承Control继承Component。
但是具体在用时有什么区别呢?这主要是从设计的角度去考虑的。
组件类和一般类的区别:我们总是习惯于面向对象的设计方式。而对象则是由类实例化而来。我们强调万事万物皆对象,把对象看作设计的基本单元。
所谓组件其实是面向组件的设计方式,我们把组件作为设计的基本单元。组件即为程序的组成部分。其实是构成程序的一个最基本的单元。一个组件其实可以包括多个类。这与传统的面向对象的设计方式有点区别。算是更高一层的封装。
而控件和用户控件其实是组件按照具体的用途的一种划分,它们都是组件。控件的突出特点就是交互式组件。而用户控件则是将某些特定的组件或控件复合从而实现特定的业务功能。所以用户控件往往是从业务角度来设计的。

2. Control.SetStyles

https://www.cnblogs.com/1175429393wljblog/p/5684090.html

3. 用户控件自定义属性

https://blog.csdn.net/im1smb/article/details/75577438

4. 用户控件自定义事件

https://www.cnblogs.com/zhuxiaoxiao/p/4905910.html

public partial class MyTextbox : TextBox
    {
        #region field

        //定义事件
        public event EventHandler EventMyTextChanged;

        #endregion

        public MyTextbox()
        {
            InitializeComponent();
            init();
        }

        private void init()
        {
            //把自定义的方法添加到TextChanged事件中
            base.TextChanged += new EventHandler(MyTextChanged);
        }

        /*
         * .NET框架设计准则说,创建一个OnEventName受保护的虚拟方法来为我们提高事件是最佳做法。
         * 这样,继承类可以通过重写该OnEventName方法来“处理”事件,
         * 这比订阅事件的性能要好一些。即使你认为你永远不会推翻这个OnEventName方法,
         * 不管怎样,养成这样做的习惯是一个好主意,因为它简化了事件提升过程。
         * 增加OnMyTextChanged就是为了后续可以继承事件。
        */
        protected virtual void OnMyTextChanged(EventArgs e)
        {
            EventHandler handler = this.EventMyTextChanged;
            if (handler != null)
            {
                handler(this, e);
            }
        }

		//自定义的方法
        private void MyTextChanged(object sender, EventArgs e)
        {
            Control control = sender as Control;
            if (control.Text == "e")
            {
                control.BackColor = Color.Yellow;
            }
            else
            {
                control.BackColor = Color.White;
            }

            OnMyTextChanged(e);
        }

        protected override void OnPaint(PaintEventArgs pe)
        {
            base.OnPaint(pe);
        }
        
    }

11. 单例模式

https://www.cnblogs.com/annkiny/p/5946932.html
单例模式:确保一个类只有一个实例,并提供一个全局访问点。(定义)
概念拆解:
(1)确保一个类只有一个实例
(2)提供一个访问它的全局访问点
个人理解:
  一个类不被new,在类里的方法不被重复的new,在多线程调用实例时,确保只有一个实例在运行。
生活中的例子:
  一个国家只有一个总统。

2.语法

1. 基础

public(共有的) 声明的方法和属性,可以被外部调用.
private(私有的) 声明的方法和属性,只能在本类中被调用,外部看不到.
static(静态的) 声明的方法和属性,不需要实例化类就能被调用,当然也有公有和私有之分.

强制转换   
Convert.ToString()        
Convert.ToInt32()
字符串转int        int.Parse(str)
十进制转二进制      System.Convert.ToString(126, 2).PadLeft(8, '0');

#### 方法

**方法的功能要单一**
**out 参数**
public static void Test(int[] nums, out int max, out int min)
一个方法有多个返回值时,返回值类型相同可以返回一个数组;
out参数:返回值多个,不限类型,使用out修饰的变量不需要return ;
**ref参数**
publlic static void Method(ref int myRefInt)
通过引用来传递参数,传递的是参数地址
**params参数**
params主要是在声明方法时参数类型或者个数不确定时使用
一.参数数组必须是一维数组  
二.不允许将params修饰符与ref和out修饰符组合起来使用   
三.与参数数组对应的实参可以是同一类型的数组名,也可以是任意多个与该数组的元素属于同一类型的变量  
四.若实参是数组则按引用传递,若实参是变量或表达式则按值传递 
五.必须是形参里的最后一个参数

**方法重载**
同一个类中定义多个方法名相同、参数列表(参数类型,参数个数)不同的方法,这样的形式我们称为方法重载

正则方法 判断字符串是否为数字
publicstaticbool IsNumeric(string value)
{
return Regex.IsMatch(value, @"^[+-]?\d*[.]?\d*$");
}
publicstaticbool IsInt(string value)
{
return Regex.IsMatch(value, @"^[+-]?\d*$");
}
publicstaticbool IsUnsign(string value)
{
return Regex.IsMatch(value, @"^\d*[.]?\d*$");
}

2. 关键字之Partial

http://blog.csdn.net/yiyelanxin/article/details/70670074
Partial是局部类型的标志。局部类型可以实现将一个类、结构或接口分成几个部分,分别放在在几个不同的.cs文件中(当然也可以放在同一个.cs文件中)。在程序进行编译之后,将会合并成一个完整的类。

3. 变量命名规范

类的私有成员带 _开头
Camel 骆驼命名规范。要求变量名的手单词的首字母大写,其余每个单词的首字母大写,多用于给变量命名
Pascal 命名规范:要求每个单词的首字母都要大写,其余字母小写,多用于给类或者方法命名

4. Abstract和Virtual的区别

https://www.cnblogs.com/zyj649261718/p/6256327.html
一、Virtual方法(虚方法)

virtual 关键字用于在基类中修饰方法。virtual的使用会有两种情况:

情况1:在基类中定义了virtual方法,但在派生类中没有重写该虚方法。那么在对派生类实例的调用中,该虚方法使用的是基类定义的方法。

情况2:在基类中定义了virtual方法,然后在派生类中使用override重写该方法。那么在对派生类实例的调用中,该虚方法使用的是派生重写的方法。

二、Abstract方法(抽象方法)

abstract关键字只能用在抽象类中修饰方法,并且没有具体的实现。抽象方法的实现必须在派生类中使用override关键字来实现。

接口和抽象类最本质的区别:抽象类是一个不完全的类,是对对象的抽象,而接口是一种行为规范。

5. 定义类成员(字段、方法、属性)

http://blog.csdn.net/qq_30594349/article/details/75212621
成员定义

  • public----成员可以由任何代码访问
  • private----成员只能由类中的代码访问(如果没有使用任何关键字,默认使用这个关键字)
  • internal----成员定只能由义他的程序集(命名空间)内部的代码访问
  • protected----成员只能由类或派生类的代码访问
  • protect和internal也可以结合使用 protected internal ,表示它们只能由项目中派生类的代码来访问
  • 用static关键字修饰,则表示它们是类的静态成员,而不是对象的实例成员

6. System.Environment.GetFolderPath的使用

string strPath = Environment.GetFolderPath(Environment.SpecialFolder.Personal);//获取的“我的文档”
Environment.SpecialFolder 枚举说明:
 成员名称 											说明 
 ApplicationData 						目录,它用作当前漫游用户的应用程序特定数据的公共储存库。 
 CommonApplicationData 				目录,它用作所有用户使用的应用程序特定数据的公共储存库。 
 LocalApplicationData 					目录,它用作当前非漫游用户使用的应用程序特定数据的公共储存库。 
 Cookies 								用作 Internet Cookie 的公共储存库的目录。 
 Desktop 								逻辑桌面,而不是物理文件系统位置。 
 Favorites 							用作用户收藏夹项的公共储存库的目录。 
 History 								用作 Internet 历史记录项的公共储存库的目录。 
 InternetCache 						用作 Internet 临时文件的公共储存库的目录。 
 Programs 							包含用户程序组的目录。 
 MyComputer 							“我的电脑”文件夹。  
 MyMusic 							“My Music”文件夹。 
 MyPictures 							“My Pictures”文件夹。 
 Recent 								包含用户最近使用过的文档的目录。 
 SendTo 								包含“发送”菜单项的目录。 
 StartMenu 							包含“开始”菜单项的目录。 
 Startup 								对应于用户的“启动”程序组的目录。 
 System 								“System”目录。 
 Templates 							用作文档模板的公共储存库的目录。 
 DesktopDirectory 						用于物理上存储桌面上的文件对象的目录。 
 Personal 							用作文档的公共储存库的目录。 
 MyDocuments 						“我的电脑”文件夹。 
 ProgramFiles 							“Program files”目录。 
 CommonProgramFiles 					用于应用程序间共享的组件的目录。

7. [Serializable]

http://www.cnblogs.com/gc2013/p/4070474.html
http://blog.csdn.net/letunihao/article/details/79530040
用于序列化的对象必须设置 [System.Serializable] 标签,该标签指示一个类可以序列化

8. App.config

https://jingyan.baidu.com/article/86fae346e262373c48121a7c.html

<?xml version="1.0"?>
<configuration>
  <appSettings>
    <!--用户注册Remoting服务端口-->
    <add key="RemotingPort" value="4500"/>    
  </appSettings> 
 
</configuration>
using System.Configuration;

ConfigurationSettings.AppSettings["RemotingPort"]

9. Tag的用法

tag本身是“标签”的意思,顾名思义,就是给控件打上标签。
当项目中有很多类型名称各不相同的控件时,可以将这些控件打上相同的标签,即,将控件的tag值设置为同一个值,如,hide、TLB等等,然后用一段代码,进行相应的操作

foreach (Control control in this.Controls)
{
	//遍历后的操作...
	if (control.Tag == "h")
	{
		control.Visible = false;
	}
}

10. 转义字符

\n   换行
\t     tab 键
\b    退格键,放置在字符串两边不起作用
\r\n   windows操作系统不认识\n换行符,认\r\n
@  ①取消 \ 在字符串中的转义作用,多用在定义路径;②将字符串按照原格式输出

11. DataTable和DataSet

DataSet可以比作一个内存中的数据库,DataTable是一个内存中的数据表,DataSet里可以存储多个DataTable。
DataSet:数据集。一般包含多个DataTable,用的时候,dataset["表名"]得到DataTable  
DataTable:数据表。  

12. Lambda表达式

https://blog.csdn.net/qq_36456952/article/details/64126983

在Lambda表达式中,输入参数是Lambda运算符的左边部分。它包含参数的数量可以为0、1或者多个。只有当输入参数为1时,Lambda表达式左边的一对小括弧才可以省略。输入参数的数量大于或者等于2时,Lambda表达式左边的一对小括弧中的多个参数质检使用逗号(,)分割。
()=>Console.WriteLine(“This is a Lambda expression.”);
m=>m+2;
(m,n)=>m*n;

12. CallerFilePath

在编译器的配合下,分别可以获取到调用函数(准确讲应该是成员)名称,调用文件及调用行号。

public static class CallerMemberNameAttributeTest
    {
        public static void Test()
        {
            UserQc userQc1 = new UserQc { NameLike = "zhang san" };
            WriteError("测试 .NET 4.5 中的 CallerMemberNameAttribute ");
        }

        /// <summary>
        /// Writes an error level logging message.
        /// </summary>
        /// <param name="message">The message to be written.</param>
        private static void WriteError(object message,
            [CallerMemberName] string memberName = "",
            [CallerFilePath] string sourceFilePath = "",
            [CallerLineNumber] int sourceLineNumber = 0)
        {
            Console.WriteLine("文件:{0} 行号:{1} 方法名:{2},消息:{3}", sourceFilePath, sourceLineNumber, memberName, message);
        }
    }

//这里的sourceFilePath就是调用者Test函数所处的原始路径,就算把生成的exe放到别的路径下,也会显示原始编译代码的路径

13. 字典

根据value获取key值
 //Linq
    var keys = dic.Where(q => q.Value == "2").Select(q => q.Key);  //get all keys
    var firstKey = dic.FirstOrDefault(q => q.Value == "2").Key;  //get first key

3. 桌面程序开发

1. 自定义窗口关闭、最小化等按钮

这里写图片描述
采用PictureBox控件

private void close_box_Click(object sender, EventArgs e)
{
    MouseEventArgs me = (MouseEventArgs)e;
    if (me.Button == MouseButtons.Left)
    {
        Form1_FormClosing(null, null);
    }
}
private void box_mouse_enter(object sender, EventArgs e)
{
	PictureBox box = (PictureBox)sender;
	String tag = box.Tag.ToString();
	//用于显示图片的函数
	box.Image = u.GetImageBySkin(tag, 1);
}

private void box_mouse_leave(object sender, EventArgs e)
{
	PictureBox box = (PictureBox)sender;
	String tag = box.Tag.ToString();
	box.Image = u.GetImageBySkin(tag);
}

private void box_mouse_down(object sender, MouseEventArgs e)
{
	if(e.Button == MouseButtons.Left){
		PictureBox box = (PictureBox)sender;
		String tag = box.Tag.ToString();
		box.Image = u.GetImageBySkin(tag, 2);
	}            
}

private void box_mouse_up(object sender, MouseEventArgs e)
{
	PictureBox box = (PictureBox)sender;
	String tag = box.Tag.ToString();
	box.Image = u.GetImageBySkin(tag, 1);
}

2. 程序只启动一次

try
{
	Process[] pro = Process.GetProcessesByName("项目程序名称");
	if (pro != null && pro.Length > 1)
	{
		MessageBox.Show("程序正在运行");
		Application.Exit();
		return;
	}

	Application.EnableVisualStyles();
	Application.SetCompatibleTextRenderingDefault(false);
	form1 = new Form1();
	Application.Run(form1);
}
catch (Exception ex)
{
	MessageBox.Show(ex.message, "系统错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
}

3. 自定义异常消息

string GetExceptionMsg(Exception ex, string backStr)
{
	StringBuilder sb = new StringBuilder();
	sb.AppendLine("****************************异常文本****************************");
	sb.AppendLine("【出现时间】:" + DateTime.Now.ToString());
	if (ex != null)
	{
		sb.AppendLine("【异常类型】:" + ex.GetType().Name);
		sb.AppendLine("【异常信息】:" + ex.Message);
		sb.AppendLine("【堆栈调用】:" + ex.StackTrace);
	}
	else
	{
		sb.AppendLine("【未处理异常】:" + backStr);
	}
	sb.AppendLine("***************************************************************");
	return sb.ToString();
} 

4. VS代码颜色

代码中红色波浪线 :语法错误; 绿色波浪线:语法没有错误,警告作用

5. VS快捷键

https://blog.csdn.net/hezhongla0811/article/details/90448226

Ctrl + E + D = 代码格式化1
Ctrl + K + F = 代码快速格式化2
Ctrl + E + C = 注释代码1
Ctrl + K + C = 注释代码2
Ctrl + E + U = 取消注释代码1
Ctrl + K + U = 取消注释代码2
Tab + Tab = 代码联想
Alt + Enter = 快速引用
Ctrl + Shift + C 新建类
Ctrl + E + E = 在交互窗口中运行选中代码(很实用)
F6 = 生成(整个解决方案中类库)
Shift + F6 = 生成(当前类库)
Ctrl + R + G = 删除无效Using
Ctrl + H = 批量替换
Ctrl + G = 跳转到指定行
Shift + F9 = 监控(代码运行时)
Shift + F12 = 查找所有引用
Ctrr + Tab + Tab = 生成无参构造器
Shift + End  / Shift + Home 选中当前行
Ctrl+E、V    复制当前行到下一行
Alt+向上键 / Alt+向下键    上移/下移行

代码片段
构造函数   ctor 回车
prop  两个tab键
propful  两个tab键

6. 安装NLog日志管理工具

https://blog.csdn.net/jun502525164/article/details/40352253

<target xsi:type="File" name="file_trace" fileName="${basedir}/logs/log_${level}_${shortdate}.log"
        layout="${longdate} ${uppercase:${level}} line: ${callsite-linenumber} ${callsite:className=true:includeSourcePath=false:methodName=true} ${message}" encoding="utf-8"/>

7. 安装Metro Framework

https://blog.csdn.net/lgj123xj/article/details/79592183

8. 安装Krypton

视频教程https://editor.csdn.net/md/?articleId=78071778
Krypton下载 https://download.csdn.net/download/lingyun410/10782750?utm_source=iteye_new

9. 安装SuperSocket

https://github.com/kerryjiang/SuperSocket

通过程序包管理器安装
如果报SuperSocket.SocketEngine error,缺少 SuperSocket.SocketEngine.dll
SuperSocket中的日志功能
https://www.e-learn.cn/topic/3449317

10. 弹出框

MessageBox.Show(outPut, "Title");

MessageBox.Show(outPut, "Title", MessageBoxButtons.OKCancel, 
MessageBoxIcon.Question);

if (MessageBox.Show("将\n选择CCIR模型", "提示", MessageBoxButtons.OKCancel, 
MessageBoxIcon.Question, MessageBoxDefaultButton.Button1) == 
System.Windows.Forms.DialogResult.OK)
            {
                var frm = new Form2();
                frm.Show();

            }
MessageBoxDefaultButton.Button1   表示弹出框首次弹出来的时候默认选中的按钮
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

huangle63

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值