C#基础(learning hard 学习笔记)

-------------------------------------------------------------华丽分割线----------------------------------------------------------------

常用关键字

as:类型转换;    

base:从派生类中访问基类的成员;用于从派生类中访问基类的成员,调用基类上已被其他方法重写的方法。指定创建派生类实例时应调用的基类构造函数;从静态方法中使用 base 关键字是错误的;除了base,访问基类成员的另外一种方式是:显示的类型转换来实现。只是该方法不能为静态方法;    

checked:对整型类型算术运算和转换显式启用溢出检查;    

decimal:表示128位数据类型,同浮点型相比,具有更高的精度和更小的范围,适合于财务和货币计算;    

extern:在方法声明中使用extern修饰符支持在外部实现方法。外部修饰符的常见方法是在使用Interop 服务调入非托管代码时与 DllImport 属性一起使用;在这种情况下,该方法还必须声明为static;[DllImport("avifil32.dll")]    public static extern void Foo();    public extern static void Fill();    

interface:可以理解为对一组方法声明进行的统一命名,但这些方法没有提供任何实现;通过接口,可以对方法进行统一管理,避免在每种类型中重复定义这些方法;在接口中定义的方法不能添加任何访问修饰符,因为接口中的方法默认为public;接口中不能包含字段、运算符重载、示例构造函数和析构函数;  接口定义了属性、方法和事件、索引器,这些都是接口的成员。接口只包含了成员的声明,无实现。成员的定义是派生类的责任。接口提供了派生类应遵循的标准结构。  

internal:只能在本程序集中访问;修饰的方法或者属性或类,Class前面默认的修饰符就是internal,不用显性使用;    

lock:将语句块标记为临界区,方法是获取给定对象的互斥锁,执行语句,然后释放该锁;

operator:重载运算符,用户自定义转换;

ref:是有进有出,必须先初始化;

out:是只出不进;

abstract:用于修饰类、方法、属性、索引器、时间,不包括字段。 使用abstrac修饰的类,该类只能作为其他类的基类,不能实例化;内部可包含已实现的函数,使用abstract以指示方法或属性不包含实现,必须在派生类中全部实现,不允许部分实现,否则编译异常,除非子类也是抽象的; 抽象方法是隐式的虚函数,只能在抽象类中声明;

virtual:用于修饰方法、属性、索引器或事件声明,并使它们可以在派生类中被重写,也可以不重写;和抽象方法的相同点是都用了override关键字进行重写方法,不同点是抽象方法必须存在于抽象类中,而子类必须重写,除非子类也是抽象的;

我们选择使用虚方法实现多态还是抽象类抽象方法实现多态,取决于我们是否需要使用基类实例化的对象;其实多态就是:同一操作作用于不同的对象,可以有不同的解释,产生不同的执行结果;允许将子类类型引用赋值给父类类型的引用,在运行时,可以通过指向父类的引用,来调用多种子类中实现的方法;

override:子类重写的基方法必须是 virtual、abstract 或 override 的;当子类对象赋值给父类时,如:‘父类’p = new ‘子类’(),override调用子类的方法,而new调用父类方法。

new:隐藏;如果想在派生类定义与基类成员同名的成员,用new将基类成员隐藏起来;如果不使用new,两个同名成员,编译器会产生告警信息;虚方法、实方法都可以被隐藏new,抽象方法、接口不可以被隐藏new。

params:来实现可变参数;

const:在编译的时候就需要有确定的值,只能用于数值和字符串,或者引用类型只能为null;const关键字可以应用于字段或局部变量;const是属于类级别而不是实例对象级别,不能跟static一起使用;没有分配内存,因为在编译后,在IL代码中嵌入了常量值;常量在c#中是默认静态的。只能通过类名访问;

readonly:关键字只应用于字段而不是局部变量;我们可以在声明或构造函数时指定readonly字段,而不是在任何其他方法中。为Readonly字段分配的动态内存,可以在我们运行时获得值。readonly仅仅用于修饰class的字段,不能修饰属性;readonly既可以是类级别也可以是实例级别,它可以与static一起使用;程序运行时才会去求值;它可以是任意类型,当然可以是object,数组,struct,它必须在构造函数或者初始化器中初始化,初始化完成之后不能被修改。通常可以定义一个readonly值为DateTime的常量。而const却无法指定为DateTime类型。

sealed: 当对一个类应用 sealed 修饰符时,此修饰符会阻止其他类从该类继承;sealed 修饰方法或属性防止它们重写特定的虚方法或虚属性;

volatile 关键字指示一个字段可以由多个同时执行的线程修改。声明为 volatile 的字段不受编译器优化(假定由单个线程访问)的限制。这样可以确保该字段在任何时间呈现的都是最新的值。volatile 修饰符通常用于由多个线程访问但不使用 lock 语句;对访问进行序列化的字段。

using:在文件顶部引用命名空间;为命名空间或类型定义别名;using 语句中使用的对象必须实现 IDisposable 接口。此接口提供了 Dispose 方法,该方法将释放此对象的资源;using只能用于实现了IDisposable接口的类型;

---2----------------------------------------------------------华丽分割线----------------------------------------------------------------

1、静态构造函数 用于初始化类中的静态成员,在创建第一个实例或引用任何静态成员之前,CLR都自动调用静态构造函数;不能使用任何访问修饰符;不能带任何参数;只会执行一次;不能直接调用静态构造函数;无法控制执行静态构造函数的时机;

2、析构函数 用于类销毁之前释放类实例所使用的托管和非托管资源;对于大多数对象,GC会自动回收;但是对于非托管资源的对象,使用完之后,GC将运行析构函数来释放它们;析构函数隐式的调用基类object的Finalize方法;不能在结构体中定义析构函数;一个类只有一个析构函数;无法继承、重载;无法显示调用,由GC自动调用;没有修饰符也没有参数;

3、索引器:当一个类包含数组时,索引器简化对数组的操作;
定义:Class PP{ [修饰符] 数据类型 this[索引类型 index];{get{} set{}} }

使用:PP p = new PP(); p[0] = 1;p[1] = 2;

4、4.1结构体中不可对声明字段初始化;4.2类中一旦定义了一个构造函数,就不会自动生成隐式构造函数;结构体中隐式构造函数都一直存在;不能显示定义无参构造函数;4.3在结构体的构造函数中,必须为结构体中所有字段赋值;4.4创建结构体对象可以不使用new,但此时结构体对象中的字段是没有初始值的;4.5结构体不能继承结构体或类,但可以实现接口;类不能继承结构体;4.6类是引用类型,结构体是值类型;4.7结构体不能定义析构函数;4.8不能使用abstract和sealed修饰结构体;

---3----------------------------------------------------------华丽分割线-----------------------------------------------------------

面向对象的编程,灵活运用:类的封装、继承、多态 三大特征;

----4---------------------------------------------------------华丽分割线-------------------------------------------------------------

1、抽象类与接口

相同点:都不能被直接实例化,都可以通过继承实现其抽象方法。  

不同点:  接口支持多继承;抽象类不能实现多继承。  
接口只能定义行为;抽象类既可以定义行为,还可能提供实现。  
接口只包含方法(Method)、属性(Property)、索引器(Index)、事件(Event)的签名,但不能定义字段和包含实现的方法; 
抽象类可以定义字段、属性、包含有实现的方法。

接口可以作用于值类型(Struct)和引用类型(Class);抽象类只能作用于引用类型。例如,Struct就可以继承接口,而不能继承类。

2、委托是一种安全地封装方法的类型;它实际上是一个能够持有对某个方法的引用的类;委托继承于SystemMulticastDelegate类型,包含构造函数和3个方法(Invoke(用来显式调用委托),IAsyncResult,EndInvoke(是两个异步方法));可传参到回调函数中,亦可直接调用委托;函数指针只能指向静态函数,而委托都可以;委托在引用非静态函数时,委托不但保存了对函数入口指针的引用,还保存了调用此函数入口的类实例的引用;

事件:是对委托的封装,C#中的事件是一个特殊的多路广播委托,默认有一个私有的委托类型变量,保存对时间处理方法的引用;并提供了对私有委托访问的方法;事件削弱了委托的功能,event在编译器角度保护了你程序的安全,因为你只能使用+=、-= 来注册事件了,而不能使用 = 为事件关联方法。(在委托中还可以使用=来绑定方法,不过=是一种破坏性代码,不管之前是否已经绑定的有方法了,他都会将其清除);

事件的定义:访问修饰符 event 委托类型 事件名;

事件的定义中还包含委托类型,即可以是自定义的委托类型,也可以是.NET库中预定义的委托类型EventHandler;

-----5--------------------------------------------------------华丽分割线---------------------------------------------------------------------

1、泛型提供的代码重用是算法的重用,即某个方法实现不需要考虑所操作数据的类型;

泛型类class MyClass<U>

泛型方法
public void ShowT<T>(T t){}
泛型接口
interface IMyGenericInterface<TKey,TValue>{}
泛型委托
delegate void Del<T>(T item);
泛型约束
//Compare<T>为泛型类,T为类型参数
public class Compare<T> where T : IComparable
{
public static T compareGeneric(T t1,T t2){}
}
//调用 Compare<int>.compareGeneric(3,4);

C#基础(learning hard 学习笔记)


2、可空类型也是值类型,但是它包含null值的值类型;int? nullable = null;

int?只是一个语法糖,提供一种方便表达的形式,C#中没有int?这个类型;int?会被编译成Nullable<int>类型;

空合并操作符??操作符,对左右两个操作符进行判断:如果左边不为null,返回左边的数,否则返回右边的数;可用于可空类型和引用类型;

3、lambda表达式:=>运算符(goes to),左边是匿名方法的输入参数,右边是表达式或语句块;
Func<string,int> delegatetest = txt => txt.Length;
调用delegatetest("ffff");

4、扩展方法能够向现有类型“添加”方法,而无需创建新的派生类型,重新编译或以其他方式修改原始类型。扩展方法必须是静态方法,可以像实例方法一样进行调用。且调用同名中实际定义的方法优先级要高于扩展方法。
先说一个熟悉的内容,LINQ表达式,其实它就是扩展方法的一种体现。也就是对String,Int,DataRow,DataTable等这些类型的基础上添加一个或多个方法,而不需要去修改或者编译类型本身。扩展方法的书写格式:它是在静态类中定义了静态方法,然后在函数第一个参数必须使用this来修饰;

那为什么扩展方法没有得到很大的推广呢?(不足之处)

1、是静态方法,使用不当会造成“污染”;

2、不具有override的能力,不会重载原有的方法

3、扩展方法会被扩展类的同名方法覆盖,所以实现扩展方法我们需要承担随时被覆盖的风险

4、扩展方法不能访问被扩展类的私有成员

5、扩展方法只能用实例来调用,不能像普通的静态方法一样使用类名调用;

6、只有引入扩展方法所在的命名空间后,扩展方法才可以使用。

扩展方法的本质

1、将实例方法调用在编译期改变为静态类中的静态方法调用,实际上,它确实拥有静态方法所有具有的所有功能。

2、作用域是整个namespace可见的,并通过使用using namespace来导入其他命名空间中的扩展方法。

3、优先级:现有实例方法优先级最高,其次为最近的namespace下的静态类的静态方法,最后为较远的namespace下的静态类的静态方法。

4、是一种编译技术,注意与反射等运行时技术进行区别,并慎重使用。

-------------------------------------------------------------华丽分割线---------------------------------------------------------------------

1、LINQ
提供一种跨越各种数据源的统一的查询方式,包含Linq to Objects、Linq to XML、Linq to DataSet、Linq to SQL;

查询表达式必须以from开头,以select或group结尾,中间可以包含一个或多个where、orderby、join等子句;

2、dynamic定义动态类型,编译器不知道它的类型,只能在程序运行时才能确定;

4、反射:

5、正则表达式: