ASP.NET框架设计(四)-----类型(下)
我们常常会问“这个对象是什么类型的?”之类的问题,但其中的“类型”又是由什么组成的呢?类型也是由一系列的成员组成的,它包含:常量、字段、方法、属性、事件等等。在我们讨论这些类型成员前我们先谈谈这些成员的可访问性。
我们先来看看一些用于成员可访问性的修饰符
CLR术语 |
C#术语 |
说明 |
Private |
private |
成员只能由定义该成员的类型中的方法或类型中嵌套类型的方法可以访问 |
Family |
protected |
成员只能由定义该成员的类型中的方法或类型中嵌套类型的方法或者该类型的一个派生类型的方法可以访问 |
Assembly |
internal |
成员只能由定义该成员的程序集中的方法可以访问 |
Family或Assembly |
protected internal |
成员只能由定义该成员的类型中所有嵌套类型、所有派生类型的方法或者定义该成员的程序集中的所有方法访问 |
Public |
public |
所有程序集的所有方法皆可访问 |
除此之外C#还提供了5个用于类型的关键字,如下表:
关键字 |
类型 |
方法、属性、事件 |
abstract |
表示该类型不能构建 |
表示构建派生类实例前必须重写派生类 |
virtual |
(不可用) |
表示该成员可由派生类型重写 |
override |
(不可用) |
表示派生类重写了基类成员 |
sealed |
表示该类型不能用作基类 |
表示该成员不可被派生类重写 |
new |
表示该成员与基类中类似成员没有关系 |
常量
常量就是值一定的量,它的值在编译时必须被确定。在编译后常量被保存在元数据中,因此这就要求常量的类型必须是基元类型。代码形式如下:
public const string x = "笑破天";
字段
字段是一种数据成员,它存放值类型实例或引用类型的引用,字段的修饰符有:
static:该状态是类型状态的一部分
Instance:C#默认情况,该字段与类型实例相关联,
readonly:该字段只能由构造器方法包含代码写入
volatile:访问该字段代码不受线程不安全优化制约
具体代码如下:
public static readonly String a = "笑破天"; //静态只读字段
public static String b = "笑破天"; //静态读写字段
public readonly String c = "笑破天"; //实例只读字段
public String d = "笑破天"; //实例读写字段
参数传递
CLR默认所有方法参数都是按值传递的。在传引用类型参数时,把对象的引用传递给方法。但CLR允许通过操作符out与ref来控制传递方式。两个操作符功能相同都是指示按引用类型传递参数,不同的是out在不在调用方法前初始化对象,运用ref必须在调用方法前初始化参数。
对于参数传递我们来看看下面一段代码:
static Int32 Add(params Int32[] values)
{
Int32 sum = 0;
for (Int32 i = 0; i < values.Length; i++)
sum += values[i];
return sum;
}
由上述代码我们看以看出调用该方法可以传递不定参数,但是params关键字必须用在方法签名的最后一个参数,必须标识是一维数组,但可以是任何类型。
属性
对于面向对象编程强调的一个很重要的概念就是数据密封,这就意味着字段永远不能够公开的对外访问。因此编写程序时大多都建议字段定义为private。鉴于这方面的考虑我们可以这么编写代码:
private String _name = "笑破天";
public String GetName()
{
return _name;
}
public void SetName(String name)
{
_name = name;
}
这种方法比较繁琐,因此CLR提供我们一种精简的编码:
private String _name = "笑破天"; //私有字段
public String Name
{
get { return _name; }
set { _name = value; }
}
事件
还记得初次接触dotnet时,双击button可以编写button默认的Click事件。我们编写程序时常常希望触发一些行为然后接受到这个行为所期望得到的效果。对于CLR而言,事件模型是建立在委托机制上的。建立一个事件我们分几个步骤:
首先我们先建立一个存放事件发送给接收者的信息类型。
public class MsgEventArgs : EventArgs
{
private String pcxpt;
public String Pcxpt
{
get { return pcxpt; }
}
public MsgEventArgs(String str)
{
this.pcxpt = str;
}
}
接着我们必须定义事件的成员
internal class MsgManager
{
public event EventHandler<MsgEventArgs> NewMsg;
}
然后我们需要引发事件的方法
internal class MsgManager
{
public event EventHandler<MsgEventArgs> NewMsg;
protected virtual void OnNewMsg(MsgEventArgs e)
{
EventHandler<MsgEventArgs> temp = NewMsg;
if (temp != null)
temp(this, e);
}
}
我们还需要出现期望的事件
internal class MsgManager
{
public event EventHandler<MsgEventArgs> NewMsg;
protected virtual void OnNewMsg(MsgEventArgs e)
{
EventHandler<MsgEventArgs> temp = NewMsg;
if (temp != null)
temp(this, e);
}
public void GetMsg(String content)
{
MsgEventArgs e = new MsgEventArgs(content);
OnNewMsg(e);
}
}
最后我们要设计一个监听这个事件的类型
public MsgManager mm;
private void Form1_Load(object sender, EventArgs e)
{
mm = new MsgManager();
mm.NewMsg += new EventHandler<MsgEventArgs>(mm_NewMsg);
}
private void button1_Click(object sender, EventArgs e)
{
mm.GetMsg("笑破天要好好学事件"); //触发事件的行为
}
void mm_NewMsg(object sender, MsgEventArgs e)
{
MessageBox.Show("小破天 说: "+e.Pcxpt+"!");
}