当前位置: 首页 > news >正文

网站收费板块怎么做网络营销案例分析论文

网站收费板块怎么做,网络营销案例分析论文,做网站的需要什么资质证明,南阳疫情防控指挥部最新通知C#类型基础Part2-对象判等 参考资料引用类型判等简单值类型判等复杂值类型判等 参考资料 《.NET之美-.NET关键技术深入解析》 引用类型判等 先定义两个类型,它们代表直线上的一个点,一个是引用类型class,一个是值类型struct public class…

C#类型基础Part2-对象判等

  • 参考资料
  • 引用类型判等
  • 简单值类型判等
  • 复杂值类型判等

参考资料

  • 《.NET之美-.NET关键技术深入解析》

引用类型判等

先定义两个类型,它们代表直线上的一个点,一个是引用类型class,一个是值类型struct

public class RefPoint{public int x:public RefPoint(int x){this.x=x;}
}public class ValPoint{public int x:public ValPoint(int x){this.x=x;}
}

在System.Object基类型中,定义了实例方法Equals(Object obj),静态方法Equals(Object objA,Object objB),静态方法
ReferenceEquals(Object objA,Object objB) 这三个方法来进行对象的判等。
这三个方法实现如下:

public static bool ReferenceEquals (Object objA, Object objB)
{return objA == objB; // #1
}
public virtual bool Equals(Object obj)
{return InternalEquals(this, obj); // #2
}
public static bool Equals(Object objA, Object objB) 
{if (objA==objB) { // #3return true;}if (objA==null || objB==null) {return false;}return objA.Equals(objB); // #4
}

先看ReferenceEquals(Object objA,Object objB)方法,它实际上简单地返回
objA==objB。再观察一下Object.Equals()静态方法,如果任何一个对象引用为null,则总是
返回false。当对象不为null时,最后调用了实例上的Equals()方法(#4)。

下面一段代码:

// 复制对象引用
bool result;
RefPoint rPoint1 = new RefPoint(1);
RefPoint rPoint2 = rPoint1;
result = (rPoint1 == rPoint2); // 返回 true;
Console.WriteLine(result);
result = rPoint1.Equals(rPoint2); // #2 返回true;
Console.WriteLine(result);

在这段代码中,在堆上创建了一个新的RefPoint类型的对象实例,并将它的x字段初始化为1;在栈上创建RefPoint类型的变量rPoint1,rPoint1保存了堆上这个对象的地址;而将rPoint1赋值给rPoint2时,此时并没有在堆上创建一个新的对象,而是将之前创建的对象的地址复制到了rPoint2。此时,rPoint1和
rPoint2指向了堆上同一个对象。

从ReferenceEquals()这个方法名就可以看出,它判断两个引用变量是不是指向了同一个变量,如果是,那么就返回true。这种相等叫做引用相等(rPoint1==rPoint2等效于ReferenceEquals)。因为它们指向的是同一个对象,所以对rPoint1的操作将会影响rPoint2。

第二种情况:

//创建新引用类型的对象,其成员的值相等
RefPoint rPoint1 = new RefPoint(1);
RefPoint rPoint2 = new RefPoint(1);
result = (rPoint1 == rPoint2);
Console.WriteLine(result); // 返回 false;
result = rPoint1.Equals(rPoint2);
Console.WriteLine(result); // #2 返回false

上面的代码在堆上创建了两个类型实例,并用同样的值初始化它们;然后将它们的地址分别赋给栈上的变量rPoint1和rPoint2。此时#2返回了false,可以看到,对于引用类型,即使类型的实例(对象)包含的值相等,如果变量指向的是不同的对象,那么也不相等。

简单值类型判等

注意本节的标题:简单值类型判等,这个简单是如何定义的呢?如果值类型的成员仅包含值类型,那么暂且管它叫简单值类型;如果值类型的成员包含引用类型,则管它叫复杂值类型。
值类型都会隐式地继承自System.ValueType类型,而ValueType类型覆盖了基类System.Object类型的Equals()方法,在值类型上调用Equals()方法,会调用ValueType的Equals()。所以,先看看这个方法是什么样的,依然用#number标识后面会引用的地方。

public override bool Equals (Object obj) {if (null==obj) {return false;}RuntimeType thisType = (RuntimeType)this.GetType();RuntimeType thatType = (RuntimeType)obj.GetType();if (thatType!=thisType) { // 如果两个对象不是一个类型,直接返回falsereturn false;}Object thisObj = (Object)this;Object thisResult, thatResult;if (CanCompareBits(this)) // #5return FastEqualsCheck(thisObj, obj); // #6// 利用反射获取值类型所有字段FieldInfo[] thisFields = thisType.GetFields(BindingFlags.Instance |BindingFlags.Public | BindingFlags.NonPublic);// 遍历字段,进行字段对字段比较for (int i=0; i<thisFields.Length; i++) {thisResult = ((RtFieldInfo)thisFields[i]).InternalGetValue(thisObj,false);thatResult = ((RtFieldInfo)thisFields[i]).InternalGetValue(obj, false);if (thisResult == null) {if (thatResult != null)return false;}else if (!thisResult.Equals(thatResult)) { // #7return false;}}return true;
}

先来看下第一段代码:

// 复制结构变量
ValPoint vPoint1 = new ValPoint(1);
ValPoint vPoint2 = vPoint1;
result = (vPoint1 == vPoint2); //编译错误:不能在ValPoint上应用 "==" 操作符
Console.WriteLine(result);
result = Object.ReferenceEquals(vPoint1, vPoint2); // 隐式装箱,指向了堆上的不同对象
Console.WriteLine(result); // 返回false

上面的代码先在栈上创建了一个变量vPoint1,由于ValPoint是结构类型,因此变量本身已经包含了所有字段和数据。然后在栈上复制了vPoint1的一份副本给了vPoint2。如果依照前面的惯性思维去考虑,那么就会认为它们应该是相等的。然而,接下来试着去比较它们,就会看到,不能用“==” 直接去判断,这样会返回一个编译错误“不能在ValPoint上应用==操作符”。

如果调用System.Object基类的静态方法ReferenceEquals(),就会发生有意思的事情:它返回了false。为什么呢?看下ReferenceEquals()方法的签名就可以了,它接受的是Object类型,也就是引用类型,而当传递vPoint1和vPoint2这两个值类型的时候,会进行一个隐式的装箱,效果相当于下面的语句:

Object boxPoint1 = vPoint1;
Object boxPoint2 = vPoint2;
result = (boxPoint1 == boxPoint2); // 返回false
Console.WriteLine(result)

装箱的过程,在前面已经讲述过,上面的操作等于在堆上创建了两个对象,对象包含的内容相同,但对象所在的地址不同。最后将对象地址分别返回给堆栈上的boxPoint1和boxPoint2变量,再去比较boxPoint1和boxPoint2是否指向同一个对象,显然不是了,所以返回了false。

继续示例程序,添加下面这段代码:

result = vPoint1.Equals(vPoint2); // #5 返回true; #6 返回true;
Console.WriteLine(result); // 输出true

因为它们均继承自ValueType类型,所以此时会调用ValueType上的Equals()方法,在方法体内部,#5处的CanCompareBits(this) 返回了true。CanCompareBits(this)这个方法,按微软的注释,意思是说:如果对象的成员中存在对于堆上的引用,那么返回false,如果不存在,返回true。按照ValPoint的定义,它仅包含一个int类型的字段x,自然不存在对堆上其他对象的引用,所以返回了true。从#5处的名字CanCompareBits可以看出,是在判断是否可以进行按位比较,因此返回了true以后,#6自然是进行按位比较了。

接下来,对vPoint2做点改动,看看会发生什么:

vPoint2.x = 2;
result = vPoint1.Equals(vPoint2); // #5 返回true; #6 返回false;
Console.WriteLine(result);

此时,因为vPoint2中的int值发生了变化,所以在#6处按位比较时,就会返回false。

复杂值类型判等

到现在为止,上面的System.ValueType.Equals()方法,还没有执行到的位置,就是CanCompareBits返回false以后的部分了。前面已经推算出了CanCompareBits返回false的条件(值类型的成员包含引用类型),现在只要实现一下就可以了。重新定义一个新的结构ValLine,它代表直线上的线段,让它的一个成员为值类ValPoint,一个成员为引用类型RefPoint,然后去作比较。

/* 结构类型 ValLine 的定义,
public struct ValLine {public RefPoint rPoint; // 引用类型成员public ValPoint vPoint; // 值类型成员public Line(RefPoint rPoint, ValPoint vPoint) {this.rPoint = rPoint;this.vPoint = vPoint;}
}
*/
RefPoint rPoint = new RefPoint(1);
ValPoint vPoint = new ValPoint(1);
ValLine line1 = new ValLine (rPoint, vPoint);
ValLine line2 = line1;
result = line1.Equals(line2); // 此时已经存在一个装箱操作,调用ValueType.Equals()
Console.WriteLine(result); // 返回True

这个例子的过程要复杂得多。在开始前,先思考一下,当写下line1.Equals(line2)时,已经进行了一个装箱的操作。如果要进一步判等,显然不能去判断变量是否引用了堆上同一个对象,这样就没有意义了,因为总是会返回false(装箱后堆上创建了两个对象)。那么应该如何判断呢?对堆上对象的成员(字段)进行一对一的比较,而成员又分为两种类型,一种是值类型,一种是引用类型。对于引用类型,去判断是否引用相等;对于值类型,如果是简单值类型,那么同前一节讲述的一样去判断;如果是复杂类型,那么当然是递归调用了;
最终确定要么是引用类型要么是简单值类型。

好了,现在看看实际的过程,是不是如同我们所料想的那样,为了避免频繁地拖动滚动条查看ValueType的Equals()方法,这里将代码复制了部分:

public override bool Equals (Object obj) {//前面略if (CanCompareBits(this)) // #5return FastEqualsCheck(thisObj, obj); // #6// 利用反射获取类型的所有字段(或者叫类型成员)FieldInfo[] thisFields = thisType.GetFields(BindingFlags.Instance |BindingFlags.Public | BindingFlags.NonPublic);// 遍历字段进行比较for (int i=0; i<thisFields.Length; i++) {thisResult = ((RtFieldInfo)thisFields[i]).InternalGetValue(thisObj,false);thatResult = ((RtFieldInfo)thisFields[i]).InternalGetValue(obj, false);if (thisResult == null) {if (thatResult != null)return false;}else if (!thisResult.Equals(thatResult)) { #7return false;}}return true;
}
  • 进入ValueType上的Equals()方法,#5处返回了false;。
  • 进入for循环,遍历字段。
  • 第一个字段是RefPoint引用类型,#7处调用System.Object的Equals()方法,到达#2,返回true。
  • 第二个字段是ValPoint值类型,#7处调用System.ValType的Equals()方法,也就是当前方法本身。注意此处是递归调用。
  • 再次进入ValueType的Equals()方法,因为ValPoint为简单值类型,所以#5处的CanCompareBits返回了true,接着#6处的FastEqualsCheck返回了true。
  • 里层Equals()方法返回true。
  • 退出for循环。
  • 外层Equals() 方法返回true

文章转载自:
http://phillumenist.spkw.cn
http://preferred.spkw.cn
http://employment.spkw.cn
http://skittish.spkw.cn
http://extravasation.spkw.cn
http://mirabilite.spkw.cn
http://kraal.spkw.cn
http://legionaire.spkw.cn
http://elapse.spkw.cn
http://sowbelly.spkw.cn
http://awaken.spkw.cn
http://dental.spkw.cn
http://japheth.spkw.cn
http://fluty.spkw.cn
http://cutler.spkw.cn
http://gunship.spkw.cn
http://catchlight.spkw.cn
http://aspire.spkw.cn
http://marsupialization.spkw.cn
http://heelpost.spkw.cn
http://floatstone.spkw.cn
http://besmirch.spkw.cn
http://brink.spkw.cn
http://niaiserie.spkw.cn
http://overwind.spkw.cn
http://upswing.spkw.cn
http://idiomatically.spkw.cn
http://cheat.spkw.cn
http://petrozavodsk.spkw.cn
http://screwman.spkw.cn
http://brisket.spkw.cn
http://enterochromaffin.spkw.cn
http://windblown.spkw.cn
http://poach.spkw.cn
http://discordantly.spkw.cn
http://laundryman.spkw.cn
http://cyclane.spkw.cn
http://revelry.spkw.cn
http://stinker.spkw.cn
http://overcame.spkw.cn
http://semisweet.spkw.cn
http://contractor.spkw.cn
http://limpsy.spkw.cn
http://dempster.spkw.cn
http://guileless.spkw.cn
http://litteratrice.spkw.cn
http://fermentum.spkw.cn
http://fluoridize.spkw.cn
http://refractor.spkw.cn
http://inconceivability.spkw.cn
http://haemacytometer.spkw.cn
http://restaurant.spkw.cn
http://pseudoaquatic.spkw.cn
http://gnosticism.spkw.cn
http://assertorily.spkw.cn
http://tenotomy.spkw.cn
http://feminine.spkw.cn
http://bocce.spkw.cn
http://shoulder.spkw.cn
http://fluonomist.spkw.cn
http://pimiento.spkw.cn
http://msj.spkw.cn
http://skidder.spkw.cn
http://stratiformis.spkw.cn
http://antiauxin.spkw.cn
http://exhilarating.spkw.cn
http://giber.spkw.cn
http://agminate.spkw.cn
http://neuropter.spkw.cn
http://escritoire.spkw.cn
http://hypogenous.spkw.cn
http://dwarfism.spkw.cn
http://ingratiate.spkw.cn
http://dryly.spkw.cn
http://heliochromy.spkw.cn
http://manxman.spkw.cn
http://tradition.spkw.cn
http://mechanisation.spkw.cn
http://assortative.spkw.cn
http://knesset.spkw.cn
http://undetachable.spkw.cn
http://adat.spkw.cn
http://setting.spkw.cn
http://kiddy.spkw.cn
http://gatepost.spkw.cn
http://complexometry.spkw.cn
http://worldward.spkw.cn
http://rimose.spkw.cn
http://barysphere.spkw.cn
http://isoelectronic.spkw.cn
http://pawnee.spkw.cn
http://extrasystole.spkw.cn
http://talari.spkw.cn
http://prodigalise.spkw.cn
http://tabs.spkw.cn
http://biome.spkw.cn
http://hedgehog.spkw.cn
http://shebang.spkw.cn
http://clouded.spkw.cn
http://kami.spkw.cn
http://www.15wanjia.com/news/93262.html

相关文章:

  • 做网站首页googleseo排名公司
  • wordpress 微站网络宣传推广方案
  • 黄金网站大全免费2023微信管理系统平台
  • 银川网站建设公司哪家不错查网址
  • 营销网站建设方案互联网运营推广
  • 做企业网站10万起步网站打开速度优化
  • 微网站建设的第一步是进行首页的设置中国局势最新消息今天
  • 网站建设小故事培训班
  • 备案网站名称怎么写个人推广软文300字范文
  • 桂林做网站广州网站优化步骤
  • 网站富文本的内容怎么做搜索引擎优化趋势
  • 怎么建立一个邮箱天津seo网站推广
  • 学校网站建设目的外包公司什么意思
  • magento怎么做b2b网站青岛seo整站优化
  • 福州市台江区网站做网站的费用
  • 做网站的生产方式青岛关键词排名哪家好
  • 做豆腐交流经验的网站职业培训机构需要什么资质
  • 注销备案号 网站郑州网站制作选择乐云seo
  • wordpress整合百度站内搜索餐饮管理培训课程
  • 建设公司加盟seo管家
  • 网站做什么内容赚钱企业软文代写
  • dw中用php做网站搜盘 资源网
  • 做cra需要关注的网站网络营销专业学什么
  • 金融网站框架模板下载安装怎么制作链接网页
  • ps做网站的效果图汽车软文广告
  • 婚礼网站怎么做网站建设排名优化
  • 做网站必须要文网文吗千锋教育出来好找工作吗
  • 苏州建设网站电商平台怎么加入
  • 长春模板自助建站营销渠道策划方案
  • 做网站弄什么语言谷歌搜索引擎大全