唤起你对c#曾经的记忆

在我们很久不进行编程开发时,往往会有种抽空的感觉,好多东西一看就懂,但是在不看时会有种茫然无意识的感觉,为了快速的恢复已有的记忆,本文从自己编程学习的经验入手,整理了我们长时间不进行程序开发,容易忘记的知识点。

									***不断更新中...**

注释

(不写注释是流氓,名字瞎起是扯淡)//借赵老师的一句话
‘///’一般用于注释函数,注释类。

快捷键

ctrl+k+d(有语法错误无法进行对齐)
ctrl+j(快速弹出只能提示)
shift+end,shift+home 键从行首到行尾,从行尾到行首;
ctrl+k+c 注释  ctrl+k+u取消注释
ctrl+R+e 快速生成属性get和set方法
alt+shift+f10 打开说明引用空间。
f1转到msdn
f12转到定义

数据类型

decimal money=5000m;(金钱类型)
String 和string在c#中都一样。String是.net平台中共用类型,string是c#中专有的,它们两个都会映射到System.class类中。

##数据类型转换
隐式类型和显式类型转换的基本要求:两种类型可以兼容。
1、隐式类型转换(自动类型转换)
小转大
例如:

	   int b=10;
	   double a=10
	   Console.WriteLine(a);

2、显式类型转换(强制类型转换)
大转小
例如:

   double b=10.4
   int a=(int)b;
   Console.WriteLine(a); 

整数的+、-、*、/、%仍然是整数
例如:
int a=10;
int b=3;
double c=a/b
得出的结果仍然是整数:3
如果想获取3.33333…,表达式中必须得有double类型的数。

命名规范

*1、Camel命名规范(多用于变量命名):首单词首字母小写,其余单词首字母大写。
*2、Pascal命名规范(多用于类或者方法命名):所有单词首字母大写。

占位符

使用方法:先挖个坑,再填个坑。
Console.WriteLine("..{0},...{1},...{2}",n1,n2,n3);

##转义符 ##
\n:换行,但是在windows系统中不认识\n,只认识\r\n;
":输出半角引号
\t:tab键(排版)
\b:退格,首尾放置无效,只是退格一个。
@:1、取消\在字符串中的转义作用。2、保留原格式输出。
##枚举##
===枚举与int和string之间转换=
@1、枚举类型默认可以和int类型相互转换 枚举类型跟int是兼容的
@2、枚举类型转换成string,用toString();
@3、字符串string类型转换成枚举类型:
枚举类型 对象名 =(枚举类型)Enum.Parse(typeof(枚举名),string s);
##Convert.ToInt32、Int32.Parse、Int32.TryParse区别
引用:Difference Between Int32.Parse(), Convert.ToInt32(), and Int32.TryParse()
1)、Int32.parse(string)
Int32.Parse (string s) method converts the string representation of a number to its 32-bit signed integer equivalent. When s is a null reference, it will throw ArgumentNullException. If s is other than integer value, it will throw FormatException. When s represents a number less than MinValue or greater than MaxValue, it will throw OverflowException. For example:

string s1 = "1234"; 
string s2 = "1234.65"; 
string s3 = null; 
string s4 = "123456789123456789123456789123456789123456789"; 

int result; 
bool success; 

result = Int32.Parse(s1); //-- 1234 
result = Int32.Parse(s2); //-- FormatException 
result = Int32.Parse(s3); //-- ArgumentNullException 
result = Int32.Parse(s4); //-- OverflowException 

2)、Convert.ToInt32(string)

Convert.ToInt32(string s) method converts the specified string representation of 32-bit signed integer equivalent. This calls in turn Int32.Parse () method. When s is a null reference, it will return 0 rather than throw ArgumentNullException. If s is other than integer value, it will throw FormatException. When s represents a number less than MinValue or greater than MaxValue, it will throw OverflowException. For example:

result = Convert.ToInt32(s1); //-- 1234 
result = Convert.ToInt32(s2); //-- FormatException 
result = Convert.ToInt32(s3); //-- 0 
result = Convert.ToInt32(s4); //-- OverflowException 

3)、Int32.TryParse(string, out int)

Int32.Parse(string, out int) method converts the specified string representation of 32-bit signed integer equivalent to out variable, and returns true if it is parsed successfully, false otherwise. This method is available in C# 2.0. When s is a null reference, it will return 0 rather than throw ArgumentNullException. If s is other than an integer value, the out variable will have 0 rather than FormatException. When s represents a number less than MinValue or greater than MaxValue, the out variable will have 0 rather than OverflowException. For example:

success = Int32.TryParse(s1, out result); //-- success => true; result => 1234
success = Int32.TryParse(s2, out result); //-- success => false; result => 0
success = Int32.TryParse(s3, out result); //-- success => false; result => 0
success = Int32.TryParse(s4, out result); //-- success => false; result => 0

Convert.ToInt32 is better than Int32.Parse since it returns 0 rather than an exception. But again, according to the requirement, this can be used. TryParse will be the best since it always handles exceptions by itself.
##字段与变量区别##
1、字段与变量的最根本区别在于字段可以存储多个值,而变量只能存储一个值。
2、字段和变量的写法区别是字段前边加一个_
例如:

public struct Person
{
	public int  _code;
	public string  _name;
	public  string  _gender;
}
//声明两个结构体
Person person1;
person1._name;
Person person2;
person2._name;
//字段可以多个值。person1的名字跟person2的名字。

##属性##
惯用法:属性开头字母大写,字段开头字母小写。

class  Person
{
	private  int age;
	
	public int Age
	{
			 set
		{
		  this.age=value;
		}
		 get
		{
		   return this.age;
		}

}

##c#中无全局变量一说,只能用静态字段来模拟全局变量。##
##c#中三大参数##
1)out参数:
如果在一个方法中返回多个相同类型的值的时候,可以考虑返回一个数组。
但是返回多个不同类型的值时就需用out。out既可以返回多个相同值也可以返回多个不同值。
其实out作用就是:返回被调用函数的多个值。与一般返回方向是相反的。
注意:out定义变量必须在被调用函数中赋值。
2)ref参数:
能够将一个变量带入一个方法中改变,改变完成后,再将改变后的值带出方法。

main()
{	
	int s=10;
	Test(ref s);

}
Test(ref s1)
{
	s1+=3
}

3)parame参数:
可变参数
将实参列表中与可变参数数组中类型一致的类型当作数组的元素。既实参可以不用声明数组。
main
{
test(“为”,34,389,34);
}
test(string name,params int[] score)
{
}
##方法的重载和返回值无关,至于方法名、参数类型、个数有关。##
##静态与非静态的区别##
1)、在非静态类中,既可以有实例成员,也可以静态方法。静态类中只能出现静态成员。
2)、在调用实例成员时候,需要使用对象名.实例成员;
在调用静态成员的时候,需要类名.静态方法。
总结:静态成员必须使用类名去调用,实例成员用对象去调用。
静态函数中只能访问静态成员,不允许访问实例成员。
实例方法既可以使用静态成员,也可以使用实例成员。
静态类中只能出现静态成员。静态类无法实例化。
使用:
1)、如果你想要你的类当做一个“工具类”去使用,这个时候可以考虑写成静态的类
2)、静态类在整个项目资源共享。静态类是占内存的。
GC Garbage Collection 垃圾回收器。
##构造函数##
作用:帮助我们初始化对象,构造函数是一个特殊的方法。
1)构造函数没有返回值,连void也没有
2)构造函数的名称必须和类名一样。
3)访问修饰符必须是public
4)创建对象的时候执行构造函数
##new##
1)在内存中开辟一块空间;
2)再开辟的空间中创建对象;
3)调用对象的构造函数初始化对象。
构造函数必须是public。
##this##
1)代表当前类的对象。
2)在类当中显式调用本类的构造函数 :this
如有多个构造函数,构建一个全属性的构造函数,其它构造函数调用这个全的构造函数,减少代码冗余。
写法:
在不全的构造函数后面加:this

	public Person(string name,int age,int english,int math,int chinese)
	{
		// 赋值给属性
		this.Name=name;
		this.Age=age;
		this.English=english;
		this.Math=math;
		this.Chinese=chinese;
	}
    public Person(string name,int english):this(name,0,english,0,0)
    //没有的可以随便给该变量赋值该类型的数
    {
	    
    }

##在一个项目中引用另一个项目的类##
1)、先引用项目
2)、引用另一个项目的命名空间。
##值类型和引用类型##
区别:
1、值类型和引用类型在内存上存储的地方不一样
2、在传递值类型和传递引用类型的时候传递的方式不一样。
值类型我们称之值传递,引用类型我们称之为引用传递。

值类型:int 、double、char、bool、decimal、struct、enum
引用类型:string、自定义类
存储:
值类型存储在内存的栈中。
引用类型存储在内存的堆中。

##字符串##
1)、字符串的不可变性,如果字符串被重新赋值,老值并不删除,而是在栈中将老的
地址删除,重新给字符串赋予新的地址值。
当程序结束后,GC扫描整个内存,如果发现有的空间没有指向,则立即销毁。
2)、可以将string类型看作是char类型的只读数组。
例:
string s=“abcde”;
//S[0]=‘B’;不能这么做,因为是只读的
//如果改变的话,首先需进行对string的转换。
char []chs=s.ToCharArray();
//将字符数组转换成我们的字符串
s=new string(chs);
Console.WriteLine(s[0]);
//字符串转字节数组:
byte buffer=Encoding.Defalut.GetBytes(str);
//字节数组转换成字符串:
string str=Encoding.Defalut.GetString(buffer);
##StringBuilder##
当字符串进行大量的循环累加时,会进行大量的开辟新的内存空间,比较慢。
计时:Stopwatch Start(); Stop(); Stopwatch.Elapsed //记录运行的总时间。
StringBuilder.Append(i);追加方式进行累加。
StringBuilder会节省很大时间,原因在于它不开辟新空间,然后再将StringBuilder转换为String
##字符串方法##
1)、Length()
2)、ToUpper()
3)、ToLower()
4)Equals(str1,StringComparision.OrdinalIgnoreCase):比较两个字符串是否一致
,并忽略大小写。
5)、Splite(字符数组,StringSplitOptions.RemoveEmptyEntries),则将字符数组内容删除,并且不返回空数组和null。
6)、Contains()
7)、Replace(str1,str2)
8)、string.Substring();
9)、string.StartWith()/EndWith()
10)、string.indexof()返回int类型,返回字符串首先出现的位置
11)、string.LastIndexof()最后一个字符串出现的位置。
12)、string.trim()移除字符串中所有空格。string.trimStart()/trimEnd();
13)、string.IsNullOrEmpty()
14)、string.Join();能够将指定的分隔符加入到数组中进行分割。
##类的继承##
子类不继承父类中的构造函数,但是,子类会默认调用父类无参的构造函数
创建父类对象,让子类可以使用父类中的成员。
所以,如果在父类中重新写了一个有参数的构造函数之后,无参数的构造函数就被干掉了。
子类就调用不到了,所以子类就会报错。
解决方法:
1、在父类中写一个无参数的构造函数。
2、在子类中显示的调用的父类的构造函数,使用关键字:base(参数)(基类的有参构造函数)。
##new关键字##
父类中有个Say()方法,子类中也有个Say()方法,理论上会隐藏,但是会有错误,
解决方法:
在子类中Say()方法前加new,隐藏后的结果就是钓不到父类的成员。
##里氏转换##
1)、子类可以赋值给父类,如果有一个地方需要父类作为参数,可以用一个子类代替。

Student s=new Student();
	Person p=s;
	或者
	Person p=new Student();
这样做的可以实现string.join("|",new string[]{"1","2","3","4"})
第二个参数是 parame object 类型,object是一切类的基类,string类型是object类的继承类。这样写可以实现任何继承于object类的继承类均可以实现join第二个参数数组形式。
2)、如果父类中装的是子类对象,那么可以将这个父类强制转换为子类对象。

Person p=new Student();
Student stu=(Student)p;//这样才能调用子类成员。

##is/as(类型转换)##
is:如果能够转换成功,则返回一个true,否则返回false
as:如果能够转换则返回一个对象,否则返回一个null

	Person p=new Student();
	Student stu=p as Student;

##ArrayList
集合:1、长度可以任意改变,类型随便。
ArrayList.Add(Object);
ArrayList.ArrayRange(数组/集合);
注:我们将一个对象输出到控制台,默认情况下 打印的就是这个对象所在的类的命名空间。
List.clear()清空所有元素。
List.Remove();删除单个元素;
List.RemoveAt(索引/下标)
List.RemoveRange(下标,长度)//根据索引删除一定范围内的元素。
List.Reverse()//将所有元素反转
List.Insert(索引,object)//在某个位置插入单个元素
List.InsertRange(索引,数组)//在指定的位置插入一个集合。
List.Contains()//判断包含内容
集合的长度问题
count/capcity
count:表示集合实际包含的元素个数.
capcity:表示集合可包含的元素个数。
实际包含的个数每次超过4就会重新申请内存空间,增加的个数为4的倍数。
##HashTable键值对集合
利用foreach循环来遍历键值对,格式:

foreach(var item in collection)
	{
	}
var:根据值可以推断类型
foreach(var item in HashTable.Keys)

##List泛型
List list=new List();//和ArrayList的区别在于它确定类型
List泛型集合转换为数组:
int[] nums=list.ToArray();//集合是int类型
##Dictionary
Dictionary <,>dic=new Dictionary<,>;
遍历可以使用

foreach(var item in dic.Keys)
{
}
或者
foreach(KeyValuePair<,>kv in dic)
{
	kv.Key..
	kv.Value..
} 

##FileStream
FileStream是用来操作字节的(任意文件)
StreamReader/StreamWriter用来操作字符的(文本文件)大文件

FileStream fsRead=new FileStream(path,FileMode,FileAccess);
byte[] buffer=new byte[1024*1024*5]
//返回实际文件长度
int length=fsRead.Read(buffer,0,buffer.Length);
//将自己数组中每一个元素按照编码格式解码成字符串
string str=Encoding.Default.GetString(buffer);
          =Encoding.Defalut.GetString(buffer,0,length);//这段代码会解码文件长度的字符串。
//关闭流
fsRead.Close();
//释放流所占的资源
fsRead.Dispose();

将创建文件流对象的过程写在using中,会帮助我们自动释放文件流所占用的资源。
using(FileStream fsWrite=new FileStream(path,FileMode,FileAccess))
{
byte[] buffer=new byte[length];
fsWrite.Write(buffer,0,buffer.Length);
}
注意:写文件和读文件都需要统一编码格式。
多媒体文件复制:


string source=pathSource;
string target=pathTarget;
创建一个读取文件的流
using(FileStream fsRead=new FileStream(pathSource,FileMode,FileAccess))
{
	//创建一个写入的流
		using(FileStream fsWrite=new FileStream(pathTarget,FileMode,FileAccess))
		{
			 byte[] buffer=new byte[1024*1024*5]
			 //因为文件可能会比较大,所以我们在读取的时候应通过一个循环去读取
			 while(true)
			 {
				//返回本次读取实际读到的字节数
				int length=fsRead.Read(buffer,0,buffer.Length);
				//如果返回0,也就意味什么都没有读到,读取完了
				if(length==0)
				{
					break;
				}
				fsWrite.Write(buffer,0,length);			
		    }
		}
}

StreamReader和StreamWriter

using(StreamReader sr=new StreamReader(path,Encoding.Default))
{
      while(!sr.EndOfStream)
	{
		sr.ReadLine();
	}
}

using(StreamWriter sw=new StreamWriter(path))
{
	string str="......";
	sr.Write(str);
}

##多态
多态:让一个对象表现出多种类型
三种:虚方法、抽象类、接口
原因:子类赋值给父类只能调用父类的方法
1)、虚方法
将父类的方法标记为虚方法,使用关键字virtual,这个函数可以被子类重新写一遍。
在子类前边加override
2)、抽象类
当父类中的方法不知道如何去实现的时候,可以考虑将父类写成抽象类,将方法写成抽象方法。(函数没有实际的价值)
标记一个类为抽象类加abstract,加入abstract的方法就是抽象方法,抽象方法没有方法体
public abstract void 函数名();
子类中重写抽象方法

public override void 函数名()
{
}

调用:
Animal a=new Dog();//抽象类无法实例
a.Bark();//方法是父类的函数,但是子类重写了,所以调用子类的函数。
抽象类与虚方法的区别在于:父类中方法有无实现。
3)、接口(属性也是两个方法,get、set,因此接口中只能有方法)
interface名字命名一般是I…albe。
#1、接口中成员不允许添加修饰符,默认就是public
#2、不允许写具有方法体的函数
#3、接口中不允许写字段
#4、接口可以继承接口
#5、如果接口即继承了类,又继承了接口,应该先写类。
#6、显式实现接口

  public interface IFlyable
  {
	  void fly();
  }
  public class Bird:IFlyable
  {
	  public void fly()
	  {
	  }
	  void IFlyable.fly()
	  {
	  }
  }

##访问修饰符
public
protected
private
internal:只能在当前程序集中访问。(当前项目内部)
能够修饰类的修饰符有两个:public 和internal
protected internal
##值传递和引用传递
值类型在复制的时候,传递的是这个值的本身。
引用类型在复制的时候,传递的是对这个对象的引用。
Person p1=new Person();
p1.Name=“张三”;
Person p2=p1;
p2.Name=“李四”;
Console.WriteLine(p1.Name);
输出应该是李四,原因是p1、p2在堆中使用同一个引用。

				|:-------栈---------:|:-------------堆----:|
Person p1		|    	p1		     |                    |

Person p2                            |	new Person();     |
p2=p1;		    |			p2	     |                    |

##序列化与反序列化
序列化就是将对象转换成二进制
反序列化是将二进制转换成对象。
作用:传输数据。
序列化:
1)、在序列化类前边加上[Serializable]
2 )、 开始序列化对象
BinaryFormatter bf=new BinaryFormatter();
bf.Serialize(fsWrite,对象类)//fsWrite创建一个FileStream类对象写对象,自动调用Write()方法。
反序列化Deserialize()
##部分类
在一个项目中如果使用两个同名类,目的是共同开发书写,在前边加一个partial
##密封类
在类前边加一个sealed
特点:密封类是不能够被继承的。
##MD5加密

//创建一个MD5对象,MD5为抽象类,无法实例化。调用Create方法创建一个对象
MD5 md5=MD5.Create();
//开始加密
byte []buffer=Encoding.Default.GetBytes(str);
//加密需要调用ComputeHash方法,方法中的参数是byte[]类型,并返回一个byte[]类型
byte []md5Buffer=md5.ComputeHash(buffer);
//将字节数组转换成字符串

//将字节数组中的每一个元素ToString();原因是会出现乱码
//return Encoding.Default.GetString(md5Buffer);

for()
{
	strNew+=md5Buffer[i].ToString("x2");//转换成16进制,加2对其
}

##进程(Process)
获取进程:Process.GetProcesses();
杀死进程:Process.Kill();
打开进程:Process.Start();
通过一个进程打开一个文件

ProcessStartInfo psi=new ProcessStartInfo(filename);
Process p=new Process();
p.StartInfo=psi;
p.Start();

##线程
单线程的问题:让程序智能做单一的一件事,容易出现假死的状态。
创建线程:

Thread th=new  Thread(方法名);
th.IsBackgroud=true;//创建一个后台线程。
th.Start();//标记着这个线程准备就绪了,可以随时被执行。

注:在.Net下是不允许跨线程的
取消跨线程访问:
在winform的form_load下:

Control.CheckForIllegalCrossThreadCalls=false;//取消对线程跨线程访问检查的设置

这样会造成异常,原因在于:该线程在使用主线程(窗体)的一些资源,关闭主线程(窗体)可能创建的线程还没有完成,它调用者主线程的资源但是主线程已经关闭了,于是就抛异常了。
解决方法:
在winform窗体的属性中点击FormClosing事件:
if(新线程!=null)
{
新线程.Abort();//关闭线程
}
具体什么时候执行这个线程由CPU决定
例如:窗体上输出从1~10000,我们可以将这个方法作为一个线程,主线程就可以对窗体进行其他操作,如移动、关闭等操作。否则的话会出现假死状态。
前台线程:只有所有的前台线程都关闭了,程序才能关闭
后台线程:只有所有的前台线程结束,后台线程自动结束,
Thread.Sleep(3000);

##委托:
1、委托是指具有相同属性(也称具有相同的函数签名:返回类型相同,参数类型、参数顺序及参数个数相同)的函数或方法的抽象,关键字为delegate。主要用途是三个:1)函数回调;2)传递方法;3)事件机制
2、匿名函数:
没有名字的函数
public delegate void DelSayHi(string name):
void mian(string [] args)
{
DelSayHi del=delegate(string name){
Console.WriteLine(“你好”+name);
});
}
// delegate就是匿名函数,没有特别说明是哪个函数。(中国、英国说你好)
lamda表达式:=>goes to
DelSayHi del=(string name)=>{Console.WriteLine(“你好”+name);};
del(“zt”);
##设计模式
这里引用刘伟老师的博客,感觉真心棒!
史上最全设计模式导学目录(完整版)

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值