面试中可能会被问到的几个关于“委托”的问题

简介:

  这几天比较清闲,刚好前段时间买了本CLR Via C#,在.Net界大家都知道Jeffrey大师的这本经典著作,惭愧一直没有拜读。

不过在C#著作中经典的非常多。读书的那时候就是通过《C#与.NET 3.0高级程序设计》这本书接触C#的,也被称为C#圣经。

CLR Via C#中的委托说的非常好,比较深入,让人耳目一新,回味无穷的感觉,看这本书的时候一定要记得带上ILDasm和

Reflector,有了他们就可以让我们更加深入的看一些问题,读书的方式有很多种,提问式的,提炼式的,因为任何东西都遵循

“八二原则“,100个字中,有营养的文字也就区区20个而已,抓住了就理解了,好了,就乱扯到这里了。

 

Q: 什么是委托

 

A: 委托就是一个继承自MulticastDelegate的类,不信可以用 ILdasm 看一下。

1   public delegate void FlyAction();

 

Q: 我从ILdasm中看到了Invoke方法,但是我在Delegate却没有看到该方法的定义?为什么?

 

A: 这其实是混淆了delegate关键字和FCL中的Delegate类型,而对于delegate关键字,编译器和CLR给我们做了很多的优化,

    并且掩盖了很多复杂的细节,而FCL中的Delegate并没有。

 

Q: 我知道可以将方法作为参数传递给委托,然后可以在任何地方通过委托的invoke来执行那个作为参数的方法,请问是如何做到的?

 

A:既然可以在任何地方引用这个参数的方法,那就要看看方法是如何入侵到委托的。

   ①  先看看实例代码:

namespace Demo
 {
     class Program
     {
         public delegate void FlyAction();
 
         static void Main(string[] args)
         {
             Bird bird = new Bird();
 
             FlyAction action = new FlyAction(bird.Fly);
 
             action.Invoke();
         }
     }
 
     public class Bird
     {
         public static Random rand = new Random();

         public void Fly()
         {
             return "i can fly " + rand.Next();
         }
     }
 }


      从第一个QA中我们也看到了,其实委托是就是类,那我new一个类时,bird.fly其实就是类的构造函数的参数。

   ② 再来看看生成的IL中的构造函数。

 

   这时候问题就出来了,为什么这里有两个参数,而new FlyAction(bird.Fly) 中却是一个参数,这里貌似是有问题的,不符合语法规

   则,其实这里还是编译器提供了一个中间层,通过这个中间层做了一个转化,从而给我们隐藏了具体逻辑。其实在delegate中提供了

    一个Target和Method属性,当我们传入bird.Fly时,Target记录了Bird这个类,Method记录了Bird中的Fly方法,所以invoke的时

   候会自动触发Bird类中的Fly方法。证据如下:

这里补充一点,当new FlyAction的时候如果是静态方法,那么Target=null的,编译器只需要通过Method就能找到触发的方法。

 

Q:为什么在多播委托中,不建议回调方法有返回值,即使有返回值,多播中的方法也只能返回最后一个值,如果我想获取每个方法

     的返回值,应该怎么处理? 实例代码如下:

class Program
    {
        public delegate string FlyAction();

        static void Main(string[] args)
        {
            Bird bird = new Bird();

            FlyAction action1 = new FlyAction(bird.Fly);

            FlyAction action2 = new FlyAction(bird.Fly);

            FlyAction action3 = new FlyAction(bird.Fly);

            action1 += action2;

            action1 += action3;

            Console.WriteLine(action1.Invoke());

            var result = action1.GetInvocationList();

            Console.Read();
        }
    }

    public class Bird
    {
        public static Random rand = new Random();

        public string Fly()
        {
            return "i can fly " + rand.Next();
        }
    }

 

A:  既然提到了“多播”,其实就是唬人了,内部源代码里面就是维护了一个List,将“多播”中的方法都放入到List中,Invoke的时候,

     就循环遍历下List来依次调用里面的方法,这就是为什么建议不要用“有返回值“的方法。

   

下面我们可以通过  GetInvocationList 来获取这个list里面的方法。

 

 

然后我们再来看看这个GetInvocationList 里面的代码是怎么写的。

 

看到了this._invocationList和for循环,是不是有一种彻底明白的感觉,如果你想获取每个方法的返回值,那只能通过

GetInvocationList拿出来后,自己手工处理了,只有这样才能拿到“多播委托”中每个方法的返回值。

 

Q:请问下最后一个问题,问完就睡觉,请问委托可以动态创建吗?

 

A:可以的。Delegate中提供了CreateDelegate方法,就是可以动态创建的,举个例子你就知道了。

class Program
    {
        public delegate string FlyAction();

        static void Main(string[] args)
        {
            Bird bird = new Bird();

            //找到类下的方法
            var method = typeof(Bird).GetMethod("Fly", BindingFlags.Instance | BindingFlags.Public);

            var mydelegate = (FlyAction)Delegate.CreateDelegate(typeof(FlyAction), bird, method);

            var result = mydelegate.Invoke();
        }
    }

    public class Bird
    {
        public string Fly()
        {
            return "i can fly " + new Random().Next();
        }
    }

 

相关文章
|
7月前
|
存储 设计模式 编译器
【C++】—— 多态常见的笔试和面试问题
【C++】—— 多态常见的笔试和面试问题
|
7月前
|
存储 算法 Java
程序员的20大Java集合面试问题及答案
程序员的20大Java集合面试问题及答案
|
7月前
|
存储 JSON JavaScript
【面试题】 面试官:你个老六,连继承都不会...
【面试题】 面试官:你个老六,连继承都不会...
|
设计模式
面试官问我什么是责任链模式,我把这篇文章甩给了他
面试官问我什么是责任链模式,我把这篇文章甩给了他
面试官问我什么是责任链模式,我把这篇文章甩给了他
|
XML Java 数据格式
面试问到IOC我该如何回答呢?
相信在面试中,只要问到Spring,基本都会抛出一个问题,说说你对Spring IOC理解吧?虽然在日常的开发经常会使用到,但是要回答起来,并不简单。大脑经过简单的头脑风暴后,蹦出了控制反转、依赖注入这样的词语。显然这些并不是面试官想听的。
|
设计模式
【面试常问】说一下你对单例模式的理解
设计模式在开发中是重中之重,尤其是单例模式,因此也就成了面试中的高频问题,决定整理一下;如有错误还请个位指正!
83 0
|
Java
【面试常问】线程中常用的方法
在我们日常开发中线程是必不可少的,那么线程中的方法也就成了面试中的高频问题,决定整理一下;如有错误还请个位指正!
75 0
|
存储 JavaScript 前端开发
面试官:你使用过IntersectionObserve方法吗?怎么用?
前言 不知道你有没有遇到过这样的问题:如何实现图片懒加载?如何判断元素进入了可视区?如何判断元素不在可视区内?等等...... 这些问题我相信绝大多数的前端小伙伴都遇到过,而且在项目中的遇到的频率还不低!我们就拿图片懒加载这种场景举例:当图片进入可视区后才进行加载。常见的做法就是通过监听 scroll 滚动事件,然后通过 getBoundingClientRect()实时获取元素的相对位置,从而判断元素是否出现在可视区内。 上面的方法需要频繁触发 scroll 事件,很容易造成卡顿或者页面性能问题。 处理这种问题,我们可以使用另一种方式:IntersectionObserve 方法。
508 0
面试官:你使用过IntersectionObserve方法吗?怎么用?
|
设计模式 安全 Java
面试官:说说单例模式!利用这个方法,我成功套路的面试官
前言 在面试的时候面试官会怎么在单例模式中提问呢?你又该如何回答呢?可能你在面试的时候你会碰到这些问题: 为什么说饿汉式单例天生就是线程安全的? 传统的懒汉式单例为什么是非线程安全的? 怎么修改传统的懒汉式单例,使其线程变得安全? 线程安全的单例的实现还有哪些,怎么实现? 双重检查模式、Volatile关键字 在单例模式中的应用 ThreadLocal 在单例模式中的应用 枚举式单例 那我们该怎么回答呢?那答案来了,看完接下来的内容就可以跟面试官唠唠单例模式了
面试官:说说单例模式!利用这个方法,我成功套路的面试官
|
设计模式 安全 Go
不惧面试:委托
不惧面试:委托
128 0
不惧面试:委托