关于变量的高级内容(二)

万能的Object

前一章我们大概的探讨了一下值类型和引用类型,由于比较解释的比较仓促会让人感觉得比较突兀,这里我还没有找到任何的解决办法。如果大家有什么很好的提议,可以留言。在这里我就来和大家讨论一下这个Object对象吧。

在此,我做一个引入,C#做桌面开发的时候,都会有一个叫做控件事件的东西,比如Button按钮控件会有鼠标单击事件,鼠标左键落下事件,鼠标在上面移动事件...等等、

这是我随便添加一个Button然后改名字成BtnChoose之后双击它添加的Click单击事件。

大家可以看一下它的函数签名,里面有一个sender,还有一个EventArgs e。其中sender的目的就是向事件订阅者传递触发者本体,而e实际上是向订阅者传递事件参数。

首先是订阅者,因为当Button.Click事件触发之后是BtnChoose_Click函数处理,所以这里的订阅者是BtnChoose_Click函数,而sender向订阅者也就是BtnChoose_Click传递触发者本身,也就是说,它向

BtnChoose_Click传递了了按钮本身,BtnChoose。之后的事情我们可以不管了,我们主要讨论的就是这个Sender。

 

我们随便添加一个代码,然后插入断点,来看看它是如何工作的。(注意,实际上可以不敲入任何代码在34行的花括号那里进行断点的)

(编者注:要善于利用断点工具来查看代码运行,对于抽象难于理解的东西我的建议就是在代码运行过程断点然后查看一下他的实体,这样助于理解)

一开始,他就给我们一个叫做Text,这可能无法证明这是一个Button,那么我们点击一下那个三角符号,进去里面找找

最终我们找到了一个Name叫做BtnChoose的属性了,没错就是这个按钮了。

(编者注:我们在编写事件的时候为了能够在事件触发以后进一步处理,一般都会将事件的触发者传递回来方便访问,因为类的声明位置与类的调用位置实际上是两个断面,为了不耦合,也为了屏蔽细节,我们一般不会将类的成员主动暴露给调用者,特别是在商业用途的类,我们更希望它是个黑盒子。所以在事件的编写上面,慢慢的都准守一个sender,e的编写模式)

那么这里就有一个疑问了,我知道这个object是一个Button,但是我怎么使用它?

所以这里就涉及到了object对象的转换了。

object是一个神奇的东西,object作为所有类型的基类,包括值类型,它首先存在的一个转换就是值类型与引用类型的转换,叫做拆箱与装箱。

装箱实际上就是把值类型转换成object,而拆箱实际上是object转化到值类型。

对于装箱以及拆箱,一般而言,装箱时不需要做任何处理的,默认支持所有对象转换成object对象,但是拆箱的时候需要使用强制转换的形式进行拆箱。

其次,object同样也适用于逆变与协变。

逆变与协变是比较难于理解的一个东西,但是我们还是可以看一开始的引入例子。

Button变成了object,这个过程我们就称之为逆变。这是派生类转换成基类的过程

很多人喜欢把派生类叫做子类,把基类称之为父类,但是我不喜欢这样强调,因为这是OOP里面的叫法,在C#里面有自己的称呼,但都一个样,不碍于理解

而object变成Button的过程叫做协变。这是基类转换成派生类的过程

(在微软官方的说明里面,逆变与协变一般用于委托、泛型以及方法和数组,没有提到对象之间的转换,但是这个做法是存在的,而且应该也很常见,这里指的对象主要是针对,基类与父类之间的转换。)

注意,基类不能单向转换,也就是说,实例一个基类之后,不能直接转化成派生类:

但是如果这样是可以的:

1.基类的实例是派生类的实例

2.派生类转换成基类调用

代码如下。可以自行折腾

    class Program
    {
        static void Main(string[] args)
        {
            fly a = new fly();
            object obj = a;
            (obj as animal).Move();
        }
    }
    /// <summary>
    /// 定义一个动物类
    /// </summary>
    class animal
    {
        public virtual void eat()
        {
            Console.WriteLine("animal.eat");
        }
        public virtual void Move()
        {
            Console.WriteLine("animal.move");
        }
    }
    class fly:animal
    {
        public new void Move()
        {
            Console.WriteLine("fly.Move");
        }
        public  void Fly()
        {
            Console.WriteLine("fly.Fly");
        }
    }

 

posted @ 2016-08-01 18:04  丹麦的鱼  阅读(419)  评论(0)    收藏  举报