对C#的认识(1)

.Net 2.0相对于.Net 1.1增加了局部类,泛型和匿名委托。

匿名委托

struct和class的区别

1. struct是值类型,class是引用类型,值类型在Stack上分配,引用类型在Heap上分配。

2. struct无法继承,class可以继承。

3. struct无默认构造器,但可添加构造器,无析构函数,无法用abstract, sealed, protected关键字(因为无法继承),可以不使用new初始化。

    class有默认构造器,有析构函数,可以用abstract, sealed, protected关键字,必须用new初始化。

protected和internal的区别

protected只有在继承的子类中可以访问,但可以跨程序集(assembly)

internal只有在同一个程序集内可以访问,但可以跨类。

默认访问权限

对于类的成员,默认访问权限是private。

对于类型(类、接口、结构等),默认访问权限是internal。

对于接口的属性及方法,默认访问权限是public。

委托和事件

委托是多路广播的,即一个委托可以指向多个方法,它维护着一个方法列表,在该委托被调用时,这些方法都会被调用。

委托指向静态方法时,最好在静态方法前面加上类名(有时是必须的),在指向实例方法时,最好也加上this关键字。

事件模型是基于发布者和订阅者模式(publisher and subscribers),任何对象都能发布一组其他对象可以订阅的事件,当发布对象触发该事件时,所有订阅者都会被通知到。事件可以看作是发布它的对象的属性,关键字event用于定义一个事件,而该事件是委托的一个特殊实例,它也是一个委托对象。事件可以说是一个具有特殊标识的委托对象。具有事件标识的委托对象有一些限制,例如它只能使用+=和-=来加载或者卸载事件处理方法,它无法使用"=new MyDelegate(M1);"这样的方式来指向某个方法,也无法通过"myobject.myevent();"的方式来调用它。不过对于发布该事件的对象来说,可以通过"this.myevent();"来调用。

.Net自带的事件处理器是一个委托,一个针对事件处理的委托,它只有两个参数,并且没有返回值,一个参数是事件源,即触发该事件的对象,另一个参数是EventArgs类的对象或者是继承了EventArgs类的类的对象,用于保存一些事件参数,这些参数可以传递给事件处理器方法来进行处理。对于有自定义参数需要传送的情况,我们可以首先实现一个继承了EventArgs类的类,然后在事件处理器方法里使用该类的对象作为第二个参数。

接口和抽象类的区别

1. 抽象类可以包含实现细节和字段成员,接口不能,不过接口可以包含属性声明。

2. 类只能继承一个抽象类,但类可以实现多个接口。

3. 抽象类可以有非公共方法和属性,但接口不能(都是公共的),而且接口中的方法和属性不能使用访问权限修饰符,例如public等。

4. 抽象类可以有静态方法和变量,以及常量,但接口不能。

5. 抽象类有构造器,但接口没有。

6. 接口及其中的方法和属性不能用static, abstract, sealed和virtual关键字修饰。

接口属性的定义

interface I1

{

      int InterfaceProperty{get;set;}

}

对于面向接口的编程,一般分三层:

1. 接口(定义方法规范)

2. 抽象类(实现接口,一般实现多个接口;定义数据成员及静态方法和变量,以及常量;如有需要,实现部分功能)

3. 具体类(继承抽象类,根据需求实现全部功能)

泛型接口和泛型类

对于泛型接口,它可以继承一般的接口,但如果是一般的接口继承或者是类实现它时,必须提供一个具体的类型,包括里面的方法参数和返回值以及数据成员,必须提供一个具体的类型。而如果是泛型接口继承或者是泛型类实现它时,则没有这个限制。

class MyClass<U, T> : I1<U>, I2<T>
{
        I1<T> i;
        public void MyMethod(I1<T> p)
        {
        }
}

可以通过编译。

不过,

class MyClass<U, T> : I1<U>, I2<T>
{
        public void InterfaceMethod(I1<T> p)
        {
        }
}

无法通过编译。因为InterfaceMethod的参数类型必须是I1<U>(注:InterfaceMethod是接口I1<U>定义的一个方法)。

class MyClass<U, T> : I1<U>, I1<T>
{
        I1<T> i;
        public void MyMethod(I1<T> p)
        {
        }
}

无法通过编译。这是由于违反了接口实现的独特性,实现了两次相同的泛型接口。

不过,

class MyClass : I1<int>, I1<long>
{
        I1<int> i;
        public void MyMethod(I1<int> p)
        {
        }
}

可以通过编译,因为I1<int>和I1<long>是两个不同的接口。

当类实现多个接口时,需要对不同接口的方法一一实现,不过如果两个接口中的方法头一模一样,则只需实现一次该方法即可,如果想对两个接口的该方法都实现,那么其中至少有一个方法必须显示实现,如"void I1.Method1()",并且该方法无法使用访问权限修饰符,即为private的访问权限(默认权限),另一个如果没有显示实现,则可以设置权限。对于已提供具体类型的泛型接口实现,如"class MyClass : I1<int>, I1<long>",也需要显示实现其中一个,当然显示实现两个也是可以的。

as操作符

as操作符用于安全地进行显示转换。使用as操作符进行显示转换时,如果转换失败,将赋予变量null值,而不是抛出异常,然后可以通过判断变量是否为null来确定转换是否成功,从而可以不使用try---catch来捕获异常。

String和string的区别

String是.Net Framework中的类而string是C#中的关键字,string映射为String,就是编译的时候编译器会把它变成String,直接写String可以让编译器少做一点点工作。

Array和ArrayList的区别

Array是个抽象类,ArrayList是个具体类,Array其实就是数组,ArrayList是个集合。

部分类的好处

1、对于代码太多的类,使用部分类可以使条理更加清晰,同时便于多个程序员同时修改一个类。

2、对于WinForm和WebForm可以使控件定义及处理逻辑分开,便于维护管理。

使用部分类的注意点

1、所有该类的部分类必须使用partial关键字,并且位于相同的命名空间下。

2、每个定义的partial类必须在访问修饰符上保持一致,如果有一个部分是抽象的或者密封的或者继承自某个类,则整个类都是这样的,各个部分之间不能矛盾,所有部分只能继承自同一个类。

3、该类实现的接口为所有部分类实现的接口的总和,即具有累加效应,又比如对于属性也是一样。

4、在某一部分类定义的字段和对象可在其他部分类中使用。

5、所有部分类必须同时被编译。

6、只适用于class,struct,interface。

Hashtable和Dictionary的区别

1、Hashtable对于值类型的存储必须装箱,获取值类型必须拆箱,效率较低,且存入的数据在遍历时是无序的,但是对于多线程的话,它允许单线程写入,多线程读取,调用Synchronized方法可以获得线程安全的类型,因而多线程使用Hashtable比较方便。

2、Dictionary由于有泛型功能,所以值类型存储不用装箱和拆箱,在没有删除过数据的情况下,遍历是有序的,根据插入数据的顺序,但是对于多线程,它不是线程安全的,必须人为用lock语句保护,因而单线程用Dictionary比较好。

转载于:https://www.cnblogs.com/loofywang/archive/2013/04/19/MyUnderstandingOfCSharp1.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值