经过前面三篇关于.NET Framework源码研究系列的随笔,相信大家都发现其实.NET Framework的实现其实并不复杂,也许跟我们自己做的项目开发差不多。本人也是这样的看法。不过,经过仔细深入的研究,我们还是会发现一下平时很难注意到的东西,而这些东西对我们完善思路,开阔眼界,锻炼良好的编码素质有着很大的意义.
我们知道.NET中所有的类型(包括:引用类型,值类型)都从Object类派生过来,由此可以说Object是所有类型的根本。那么今天我们就研究.NET(C#)中一切元素的根本---System.Object。
Object类在.NET源码中的实现很简单,一共不过100行左右的代码,这也是我们有精力可以仔细研究它的每一行代码。先看它的定义.
1 [Serializable()]
2 [ClassInterface(ClassInterfaceType.AutoDual)]
3 [System.Runtime.InteropServices.ComVisible(true)]
4 public class Object
由定义来看,Object好像是一个普通的类(莫非Object也从Object派生而来?! ^_^ )。Serializable标签说明了Object可以做序列化反序列化操作。
ClassInterface(ClassInterfaceType.AutoDual),System.Runtime.InteropServices.ComVisible(true)是.NET为了支持COM特别设计的。除非你要手动包装COM,否则对于绝大部分时间都是用托管代码而言的人没什么意义。
1 [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
2 public Object(){ }
3 [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
4 ~Object() {}
从上面的代码看到Object只有一个空方法体的构造函数,这就是宇宙起源一样,刚开始什么都没有。此处要特别说明的是ReliabilityContract标签。ReliabilityContract定义某些代码的作者和依赖于这些代码的开发人员之间的可协靠性定。这是官方的定义,听起来有些玄乎。ReliabilityContract有两个属性,分别是两个枚举:Cer和ConsistencyGuarantee.Cer指在受约束的执行区域内调用时指定方法的行为;ConsistencyGuarantee指可靠性协定。看MSDN对这两个枚举的说明后,我们发现 [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]为Object提供了安全性保证,就是说我们在调用Object构造函数时不管有没有遇到异常情况,总会获知执行结果。
另外,Object显式定义了析构函数(又是一个不推荐的做法,好像微软很喜欢做的不推荐我们做@_@||),让我们能够手动释放对象占用的资源而不需要等到GC自动释放。
要特别说明的是,这里有个我们很少遇到的一个概念:CER,即受约束的执行区域,是创作可靠托管代码的机制的一部分。CER 定义一个区域,在该区域中公共语言运行库 (CLR) 会受到约束,不能引发可使区域中的代码无法完全执行的带外异常。在该区域中,用户代码受到约束,不能执行会导致引发带外异常的代码。
看完构造函数后我们看下Object中最常用的三个方法的实现,代码如下:
public virtual String ToString(){
return GetType().ToString();
}
[MethodImplAttribute(MethodImplOptions.InternalCall)]
public extern Type GetType();
public virtual bool Equals(Object obj){
return InternalEquals(this, obj);
}
[MethodImplAttribute(MethodImplOptions.InternalCall)]
internal static extern bool InternalEquals(Object objA, Object objB);
public virtual int GetHashCode(){
return InternalGetHashCode(this);
}
[MethodImplAttribute(MethodImplOptions.InternalCall)]
internal static extern int InternalGetHashCode(Object obj);
感觉有的悲剧,因为这三个方法什么都没做,直接调用了CLR的内部方法,看来Object也是个马甲:( 。微软官方号称Object类是所有类的基类在此恐怕要打个问号。我猜想此Object非彼Object。说不定CLR中也有一个Object。
如果说上面三个方法有点让人无语,那么下面的代码就更让人困惑了。
private void FieldSetter(String typeName, String fieldName, Object val){
FieldInfo fldInfo = GetFieldInfo(typeName, fieldName);
if (fldInfo.IsInitOnly)
throw new FieldAccessException(Environment.GetResourceString("FieldAccess_InitOnly"));
System.Runtime.Remoting.Messaging.Message.CoerceArg(val,fldInfo.FieldType);
fldInfo.SetValue(this, val);
}
private void FieldGetter(String typeName, String fieldName, ref Object val){
FieldInfo fldInfo = GetFieldInfo(typeName, fieldName);
val = fldInfo.GetValue(this);
}
private FieldInfo GetFieldInfo(String typeName, String fieldName){
Type t = GetType();
while (null != t){
if (t.FullName.Equals(typeName)){
break;
}
t = t.BaseType;
}
if (null == t){
throw new RemotingException(String.Format(CultureInfo.CurrentCulture,Environment.GetResourceString("Remoting_BadType"),typeName));
}
FieldInfo fldInfo = t.GetField(fieldName, BindingFlags.Public|BindingFlags.Instance |BindingFlags.IgnoreCase);
if (null == fldInfo){
throw new RemotingException(String.Format(CultureInfo.CurrentCulture,Environment.GetResourceString("Remoting_BadField"),fieldName, typeName));
}
return fldInfo;
}
上面一段代码似乎读取或设置一个字段的值(我们也是这样的做法)。问题时,我根本没有找到Object中用到这几个方法的地方,private又决定了扩展类也不可能访问。那么这三个方法到底有什么用,恐怕只有微软自己知道了。
小结
经过上面的分析,我们发现Object实现其实很简单,几乎没有内容。但Object中出现的CER给我们撰写高安全性代码带来一点思考。