用户操作
[即时聊天] [发私信] [加为好友]
CLR & Silverlight ShanghaiID:SilverlightShanghai
63436次访问,排名1723,好友2人,关注者12人。
SilverlightShanghai的文章
原创 34 篇
翻译 1 篇
转载 0 篇
评论 94 篇
CLR & Silverlight Shanghai的公告
如果你对CLR或Silverlight有什么意见或建议,欢迎通过导航条中的EMAIL给我们留言。有技术问题欢迎访问MSDN中文论坛进行提问(请参阅链接)。 贴子以"现状"提供且没有任何担保也没有授予任何权利。如果需要转载、录用文章,必须点击“联系作者”与博客管理员书面联系取得许可。
最近评论
fuadam:.net平台真是越做越完美了,可惜公司商用不会轻易升级平台。
modongxi:报一个Bug吧,在WinForm中想用mshtml.HTMLFormElement.elements属性获得WebBrowser控件中指定Form的所有Element,应该返回一个HTMLElementCollection,却返回一个HTMLFormElement,晕啊!
modongxi:在VS的代码编辑器内能不能实现以下两点:
1、像Delphi一样,把光标定位在一个方法或变量上时,按住Ctrl键,然后点击鼠标左键就能跳到其定义,现在还要点击鼠标右键选择,比较麻烦;
2、像Eclipse一样,选择一个变量后,所有引用该变量的地方都高亮显示;
aday:昨天看了一些第三方的silverlight组件,非常丰富,功能也非常强,silverlight还是非常有潜力,毕竟silverlight刚出来不久,相信微软的雄厚实力!
jscripter:说实话,这个东西离我的期望还有很大距离,它的控件还是不及Flex丰富,比如说,业务开发常用的TreeList就没有,DataGrid的功能不及Flex的AdvancedDataGrid,不过比较好的是开发工具不花钱,可以直接拿Visual Web Developer Express做,这还不错,就是没有可视化编辑XAML的地方,还是要买Blends
文章分类
收藏
    相册
    个人博客
    CLR & Silverlight上海开发团队MSDN上的家(RSS)
    微软STBC服务器与开发工具事业部(中国)的博客(RSS)
    走近我们的开发人员:ATField的专栏(RSS)
    技术论坛
    Silverlight技术MSDN中文技术论坛(RSS)
    存档
    订阅我的博客
    XML聚合  FeedSky
    订阅到鲜果
    订阅到Google
    订阅到抓虾
    订阅到BlogLines
    订阅到Yahoo
    订阅到GouGou
    订阅到飞鸽
    订阅到Rojo
    订阅到newsgator
    订阅到netvibes

    原创 .NET中的虚函数收藏

    新一篇: DLR in Silverlight  | 旧一篇: 大学生眼中的Silverlight

    面向对象的程序设计有三大要素,封装、继承和多态。虚函数是多态的重要组成部分,同时又在类的继承关系中有着很多变化。本文讨论.NET中对虚函数的支持。

     

    首先,我们通过一个例子来看看虚函数的普通用法:

     

    class CA {

            public virtual void Foo() {

                Console.WriteLine("CA.Foo");

            }

        }

     

        class CB : CA  {

            public override void Foo() {

                Console.WriteLine("CB.Foo");

            }

    }

     

    class Test  {

            public static void InvokeFoo(CA ca)   {

                ca.Foo();

            }

            public static void Main()    {

                InvokeFoo(new CB());

            }

    }

     

    输出结果

    CB.Foo

     

    在这个例子中,尽管在调用InvokeFoo()的时候,CB被转换成CA,但是当执行ca.Foo的时候,仍然调用了CBFoo。因为ca此时指向的是一个CB类型的对象。这种调用模式,我们称之为运行时绑定。因为在编译InvokeFoo时,编译器无法获取参数ca的真实类型,只有在运行的时候,才能根据ca的真实类型,决定调用哪一个函数。

     

    在这个例子中,两个关键字值得我们注意,首先是virtual,他告诉编译器,当前函数需要运行时绑定。其次是override,他告诉编译器,我要覆盖基类中的Foo()

     

    看到这里,可能读者会对两个问题持有疑惑:

     

    [问题]: 不用virtual结果如何?

    [问题]: 不用override结果如何?

    读者不妨自己动手修改上例,尝试这两个关键字的不同组合,看看输出的结果如何。在这里,我仅给出组合条件和其输出结果。

     

    序号

    基类(CA)中是否有virtual

    子类(CB)中是否有override

    输出

    1

    CB.Foo

    2

    CA.Foo

    3

    编译错误

    4

    CA.Foo

     

    我希望通过对这组实验结果的解释,交待一些.NET中虚函数的相关概念。

     

    运行时绑定仅体现在虚函数中。因此在试验4中,输出的结果是CA.Foo。因为Foo没有被申明为virtual,在编译阶段,已经把ca.Foo绑定到CA.Foo

     

    Override只能用于虚函数中。当子类继承基类,他便拥有了基类所有的函数,Override修饰的函数,将替换基类原来的函数。否则,子类会新增加一个函数,并同时保留基类中的函数。 下面的这个例子,很好的说明了这个问题

     

    class CA  {

            public virtual void Foo()  {

                Console.WriteLine("CA.Foo");

            }

        }

     

        class CB : CA  {

            public override void Foo()   {

                Console.WriteLine("CB.Foo");

            }

        }

     

        class CC : CA   {

            public new void Foo()   {

                Console.WriteLine("CC.Foo");

            }

        }

     

        class Test   {

            public static void Main()   {

                Console.WriteLine(typeof(CB).GetMethods().Length);   // 输出5

                Console.WriteLine(typeof(CC).GetMethods().Length);   // 输出6

            }

        }

     

    这段程序输出CBCC的函数个数,CB5个函数中,4个来自于Sysetm.Object,剩下的一个就是FooCC中多了一个函数,因为使用了new (如果不使用new,也是相同的结果,因为C#编译器默认使用new,但不显示指明new会给出一个警告),说明了CC.Foo是一个不同于CA.Foo的虚函数。

     

    所以,在试验2中,不使用override,我们在InvokeFoo中调用的还是CA.Foo()。虽然这个时候还是运行时绑定,但是因为CB.Foo并没有覆盖CA.Foo,因此我们还是得到了基类的实现。

    当一个函数不是虚函数的时候,子类中相同签名的函数总是覆盖了父类中的函数,并不需要override关键字。所以c#编译器会把它当作一个错误,如上表中试验3所示

     

    如果读者理解了上面的内容,那么来看看一个略微复杂的情况:我们邀请interface出场!

     

    interface IA   {

            void Foo();

    }

        class CA: IA  {

            public void Foo()  {

                Console.WriteLine("CA.Foo");

            }

    }

     

    [问题]: Foo是虚函数吗?

    答案是肯定的,就像interface方法不能显示声明为public一样,我们也不能在IA.Foo前面加上virtual。原因很简单,所有的interface方法都是虚函数!在调用interface方法的时候,总是要使用运行时绑定。

     

    [问题]: CA实现IA,那么CA.Foo前面需要override吗?

    答案是否定的,C#中,继承和实现是截然不同的两个概念,尽管在语法上很相似。继承意味着全盘接收基类的函数,而实现只是一个契约,保证当前类会提供interface中声明的函数,而不会接受基类的函数(事实上也不能,因为interface中没有函数的实现)

     

    [问题]: CA实现IA,那么CA.Foo前面需要virtual吗?

    答案是需要的,否则的话,CA的子类将无法覆写Foo,下面的代码是CA.FooIL声明,我们发现了关键字final(注:这里的finalIL语言的关键字,和C#sealed有些类似,意味着子类不能override当前函数)

    .method public hidebysig newslot virtual final

              instance void  Foo() cil managed

     

    下面一段代码紧接着上面的代码,读者可以猜测一下输出,看看是否掌握了本文今天讲述的内容,我会在下期博客中讲解其原委,并且和大家进一步通过IL来研究.NET中的虚函数。

     

    class CB : CA, IA  {

            public void Foo()   {

                Console.WriteLine("CB.Foo");

            }

    }

    class Test   {

            public static void InvokeFoo(CA ia)  {

                ca.Foo();

            }

            public static void Main()   {

                InvokeFoo(new CA());

                InvokeFoo(new CB());

              }

     

    By com.microsoft.stbc.devdiv.ndp.interop.dev/mountaintai二世

    发表于 @ 2008年08月21日 10:33:00|评论(loading...)|收藏

    新一篇: DLR in Silverlight  | 旧一篇: 大学生眼中的Silverlight

    评论

    #Yashmak 发表于2008-08-21 16:12:13  IP: 131.107.0.*
    首先, 请博主使用 "虚方法" 而不是 "虚函数" 这个概念, 以便不引起不必要的误解.

    博主似乎误解了 "虚方法(virtual method)" 和 "抽象方法(abstract method)" 的概念吧??

    接口中定义的方法是 "抽象方法", 而非 "虚方法". C#中的"抽象方法"不等同于"虚函数".
    "所有的interface方法都是虚函数"的论断是错误的.
    #fuadam 发表于2008-08-21 20:36:40  IP: 60.24.48.*
    Yashmak
    请先研究下CLR的基本概念
    #fuadam 发表于2008-08-21 20:44:36  IP: 60.24.48.*
    想请教下博主
    .net1.1以后接口方法的调用是通过
    call dword ptr ds:[00750010h] 这种方式来进行调用的

    我想知道全局接口表地址和在表的偏移是怎么得到的
    #Yashmak 发表于2008-08-22 14:35:22  IP: 131.107.0.*
    fuadam

    对,我之前的理解确实有问题. 当实现一个接口方法时,如果没有使用virtual关键字, 编译出的IL会将该方法标记为vitrual+final. 这就导致了在此实现类的子类中不能再次override此方法(我据此认定了 "abstract method" 不一定是 "virtual method").
    如果在实现时使用了virtual关键字, 则不会产生final修饰.
    #lifeatms 发表于2008-09-14 15:35:24  IP: 71.227.232.*
    ...
    楼上两位,virtual method,或者说virtual function table,并不是什么.NET特有的东西,理解一下native code更容易帮你了解这些,比如offset怎么来的。
    发表评论  


    当前用户设置只有注册用户才能发表评论。如果你没有登录,请点击登录
    Csdn Blog version 3.1a
    Copyright © CLR & Silverlight Shanghai