CRL:公共语言运行库 或者 .net运行库,是.net framework的核心
IL(Intermediate Language):中间语言,Microsoft Intermediate Language,MSIL 微软中间语言
JIT编辑: Just In Time Compilation 及时编辑
在.net中,编译分为两个阶段:
1)将源代码编译为微软中间语言
2)CRL将IL编译为平台专用的代码
类型判断使用var关键字,编译器根据变量的初始值推断变量的类型
预定义数据类型:值类型,引用类型(string,Object)
值类型存储在堆栈中,引用类型存储在托管堆上
C#转义字符:"C:\\Report\\image.cs" 等价于 @"C:\Report\image.cs"
枚举是用户定义的整数类型
C#预处理器指令:
#if #else #endif #error #warning #region #endregion
#if DEBUG
console.WriteLine("x is :"+x);
#endif
可选参数:
必须为可选参数提供默认值,可选参数还必须是方法定义的最后一个参数
方法重载:
方法名称相同,但是参数个数不同或类型不同的方法
属性
public string Name
{
get{return _name;}
private set{_name=value;}
}
public int Age{get;private set;}
结构:结构是值类型,不支持继承,派生自System.ValueType
struct Test{ public string length;public}
//合法,结构是值类型分配在堆栈上,声明的时候就在栈中分配空间
//如果Test是一个类就会报错,因为test是未初始化的引用,不指向任何地方的一个地址
Test test; test.length=5;
结构适用于小的数据结构,当作为参数传递或者把一个结构赋予另一个结构时,
结构的所有内容都被复制(对于类,只复制引用),容易造成性能损失
Object类
所有的.net类都派生自System.Object,如果定义类的时候没有指定基类,编译器会自动假定这个类派生自Object.
System.Object()方法
ToString():为虚方法,可以在自己定义的类中重写 public override string ToString(){.....}
GetHashCOde() Equals() Finalize() GetType() MenberwiseClone()浅复制
虚方法
把一个基类函数声明为virtual,就可以在任何派生类中重写该函数:
Class MyBaseClass
{
public virtual string VirtalMethod()
{
return "this method is virtual and defined in MyBaseClass";
}
}
泛型
System.Collections System.Collections.Generic
从值类型转化成引用类型称为装箱
List<T>
var list=new List<int>();
var stringList=new List<string>();
var classList=new List<MyClass>();
classList.Add(new MyClass());
语法糖:指计算机语言中添加的某种语法,这种语法对语言的功能并没有影响,但是更方便程序员使用。
通常来说使用语法糖能够增加程序的可读性,从而减少程序代码出错的机会。
yield是C#的一个语法糖.
如果在语句中使用yield关键字,意味着它出现的方法、运算符或get访问器是迭代器。通过使用yield定义
迭代器,可在实现自定义集合类型的IEnumerable和IEnumberator模式时无需其他显式类
IEnumerable<T>派生自IEnumerable
协变、抗变(逆变):
所谓的协变,可以理解成:父类 -> 子类。父类的对象用子类替换,也可以理解成子类当父类用。
所谓的抗变,可以理解成:子类 -> 父类。子类的对象用父类替换,也可以理解成父类当子类用。
如果泛型类型用out关键字标注,泛型接口就是协变的。这也意味着返回类型只能是T
如果泛型类型用in关键字标注,泛型接口就是抗变的。这样,接口只能把泛型类型T用作其方法的输入
元组:数组合并了相同类型的对象,元组合并了不同类型的对象
可空类型 long?
类型转换:只能从较小的整数类型隐式转换为较大的整数类型,不能从较大的整数烈性隐式转换为较小的整数类型
long.Parse(string) int.Parse(string) short.Parse(string) .....
委托:
把方法传递给其它方法时,需要用到委托。
委托是一种特殊类型的对象,以前定义的所有对象都包含数据,委托包含的只是一个或多个方法的地址。
委托的运用和类类似,先定义委托,再创建一个或多个委托的实例。
1)定义委托
委托为方法的签名和返回类型指定名称
委托语法类似于方法的定义,但没有方法体,定义的前面要加上关键字delegate
ex:定义一个委托,该委托表示的方法包含两个long 型的参数,返回类型为double
delegate double TwoLongsOp(long first,long second)
2)使用委托
C#中,委托的构造函数不能为空,委托在语法上总是接收一个参数的构造函数,这个参数就是委托引用的方法,这个方法必须匹配最初定义委托时的签名
泛型Action<T>委托和Func<T>委托是系统定义的两个泛型委托。
Action<T>委托表示引用一个返回类型为Void的方法。这个委托存在不同的变体,可以传递之多16个不同的参数类型。
同时,没有泛型参数的Action类可以调用没有参数的方法。例如,Action<in T>表示有一个输入参数的方法,Action<in T1,in T2>表示有两个输入参数的方法。
Func<T>可以以类似的方法使用。不过Func<T>允许调用带返回参数的方法。Func<T>也有不同的变体,之多可以传递16个参数和一个返回类型。
例如:Func<out TResult>委托类型可以无参的带返回类型的方法,Func<in T1,inT2,out Tresult>表示带两个参数和一个返回类型的方法。
需要记住一个东西,Action<T>中的T可以有多个,但这些T类型都表示不同的输入类型。Func<T>可以表示带输出的方法,T可以有多个,
且只有最后一个表示输出即最后一个是返回类型。Func<in T1,inT2,out Tresult>中的字符in、out在实际代码中是不会出现的。在VS中,可以通过IntelliSense查看
比较一下,其实泛型委托和自定义的委托在使用上没什么不同。只不过泛型委托Func<T>系统已经为我们定义好了,直接使用就可以了,
不需要再进行这样的定义delegate double DoubleOp(double x);。另一个泛型委托Action <T>的使用也是一样的,只不过不能有返回类型而已。
多播委托,按顺序调用多个方法,此时委托的签名必须是void,否则只能得到委托调用的最后一个方法的结果
+= -+
lambda表达式:只要有委托参数类型的地方,都可以使用lambda表达式
string mid = ",middle part,";
Func<string, string> lambda = para =>
{
para += mid;
para += " and this was added to the string.";
return para;
};
Console.WriteLine(lambda("Hello word!"));
事件:本质上是一个委托链。在使用事件的时候,必须要声明对应的委托,而触发事件,其实就是在使用委托链
事件发布者、事件订阅者(发布者可对应多个订阅者,1:n)
事件发布者对象中定义委托,以及委托类型的事件,发布事件的方法。
事件订阅者中定义委托方法。
应用中,事件订阅者需要在发布者对象中注册(即为发布者对象事件添加委托实例),然后调用
发布者对象中触发事件的方法,即调用订阅者方法。
(经典案例:裁判枪声响起,运动员开始跑步。)
在C#的event中,委托充当了抽象的Observer接口,而提供事件的对象充当了目标对象。委托是比抽象Observer接口更为松耦合的设计。
.Net Framework的编码规范:
一、委托类型的名称都应该以EventHandler结束。 handler:处理器
二、委托的原型定义:有一个void返回值,并接受两个输入参数:一个Object 类型,一个 EventArgs类型(或继承自EventArgs)。
三、事件的命名为 委托去掉 EventHandler之后剩余的部分。
四、继承自EventArgs的类型应该以EventArgs结尾。
观察者模式:也被称为发布-订阅(Publish/Subscribe)模式,它属于行为型模式的一种。观察者模式定义了一种一对多的依赖关系,
一个主题对象可被多个观察者对象同时监听。当这个主题对象状态变化时,会通知所有观察者对象并作出相应处理逻辑。
System.String 是一个类,专门用于存储字符串
StringBuilder类 两个属性:Length,Capacity 默认情况下Capacity比length大
当需要操作很长的字符串,或者要对字符串进行非常频繁的操作时,应该使用StringBuilder,
其余场合,用String比较方便。
StringBuilder sb=new StringBuilder("hello word!");//初始化
sb.Remove(0,sb.length);//删除从某位置开始某一长度的字符
sb.Apend("Hello StringBuilder");//添加内荣
sb.Clear();//清空
sb.Length=111;//Length不是ReadOnly的,可修改
sb.AppendLine("this is a new Line");//新建一行
sb.ToString();//转换为string
正则表达式:专门用于字符串处理的语言。
添加引用using System.Text.RegularExpressions;
正则表达式生成器
集合:
大多数集合类都可以在System.Collections和System.Collections.Generic名称空间中找到
泛型集合位于System.Collections.Generic名称空间中
泛型类List<T> 实现了IList,ICollection,IEnumerable,IList<T>,ICollection<T>,IEnumerable<T>
List<T>的AddRange() 方法:一次给集合添加多个元素
var racers=new List<Racer>(20){henry,Sam,KEtty};
racers.Add(new Racer());//一次添加一个元素
racers.AddRange(new Racer(),new Racer());//一次添加多个元素
racers.Insert(index,new Racer());//在指定位置插入
.RemoveAt(index);//
.RemoveRange(index,count);//
.indexOf();//
.Find();
.Sort();
....
泛型类队列Queue:System.Collections.Queue类标识对象的先进先出集合,
存储在Queue(队列)中的对象在一端插入,从另一端移除
能对集合进行顺序处理,先进先出
能接受null值,允许重复的元素
Queue myQ = new Queue();//创建一个队列
myQ.Enqueue("The");//入队 Enqueue:将对象添加到 Queue 的结尾处。
myQ.Enqueue("quick");
myQ.Enqueue("brown");
myQ.Enqueue("fox");
myQ.Enqueue(null);//添加null
myQ.Enqueue("fox");//添加重复的元素
//Dequeue 移除并返回Queue第一个元素(队列第一个)
Console.WriteLine("(Dequeue)\t{0}", myQ.Dequeue());
//Peek 返回位于队列开始处的对象(第一个元素)
Console.WriteLine("(Peek) \t{0}", myQ.Peek());
// 打印队列中的所有值
Console.Write("Queue values:");
PrintValues(myQ);
public static void PrintValues(IEnumerable myCollection)
{
foreach (Object obj in myCollection)
Console.Write(" {0}", obj);
Console.WriteLine();
}
默认值:public T GetDocument()
{
T doc =default(T)
}
栈:Stack<T>后进先出,和队列类似都实现IEnumerable<T> 和ICollection接口
链表:LinkedList<T>是一个双向链表
优点是将元素插入到列表中间位置时,只需要修改上一个元素的next引用以及下一个元素的previous引用。
在List<T>中插入一个元素,需要移动钙元素后面的所有元素
有序列表:SortedList<TKey,TValue>
使用场景:需要机遇键对所需的集合排序
字典:Dictionary<TKey,TValue>
有序字段:SortedDictionary<TKey,TValue>
集:包含不重复的元素的集合称为集(set)
ISet<T>,创建合集、交集,获取超集,子集
位数组:如果需要处理的数字有很多位,就可以使用BitArray和BitVector32
并发集合:线程安全的集合类,防止多个线程以相互冲突的方式访问集合
ildasm工具
Windows使用一个系统:虚拟寻址系统,该系统把程序可用的内存地址映射到硬件内存中的实际地址上,这些任
由Windows在后台管理。这些内存被称为虚拟地址空间,或虚拟内存,一般直接叫内存。内存中有一个区域称为栈。
栈指针:(是操作系统中维护的一个变量)指栈中下一个空闲存储单元的地址,栈是向下填充的,即从发高内存地址向低内存地址填充。
当数据入栈后,栈指针就会随之调整,以始终指向下一个空闲存储单元。
托管堆(简称为堆):是内存中的另一块区域。
指针:unsafe关键字 语法: int * pValue;