即日起在codingBlog上分享您的技术经验即可获得积分,积分可兑换现金哦。

不惧面试:.NET编程之委托

微信 DotNet 9℃ 0评论

(点击上方蓝字,可快速关注我们)


来源:jackson0714

cnblogs.com/jackson0714/p/5111347.html


写在前面


如果您对以下的可能面试问到的题有所疑惑或不知道这些知识点,请继续往下看,如果对您有所帮助

面试常见题:

1.委托是什么?★☆

2.为什么需要委托?★☆

3.委托能用来做什么?★☆

4.如何自定义委托★☆

5..NET默认的委托类型有哪几种?★☆

6.怎样使用委托?★★★

7.多播委托是什么?★★★

8什么是泛型委托?★★★

9.什么是匿名方法?★★

10.委托是否可以回调实例方法★★★

11.Lambda表达式是什么?★

12.Lambda表达式怎么传参?★★★

13.Lambda多行代码怎么写?★★

14.什么是闭包?★★

看完这些题目,心中是否有疑惑呢?那就接着看呗,我来帮您解答心中的疑惑

1.委托是什么?★☆

本题主要考察委托的概念:委托是寻址的.NET版本。在C++中,函数指针只不过是一个指向内存位置的指针,它不是类型安全的。我们无法判断这个指针实际指向什么,像参数和返回类型等项久更无从知晓了。

而.NET委托完全不同,委托是类型安全的类,它定义了返回类型和参数的类型。委托类不仅包含对方法的引用,也可以包含对多个方法的引用。

2.为什么需要委托?★☆

本题主要考察直接调用一个方法和通过委托来间接调用委托的区别。

在很多场景下直接调用方法是比较简单方便的,但是在某些场景下,使用委托来调用方法能达到减少代码量,实现某种功能的用途,比如说事件。

3.委托能用来做什么?★☆

本题主要考察委托在我们写code时的用途。一个笼统的准则:当要把方法传给其他方法时,需要使用委托。比如下面几个场景:

a.启动线程和任务

调用System.Threading.Thread的一个实例上使用方法Start(),必须为计算机提供开始启动的方法的袭击,

即Thread类的构造函数必须带有一个参数,该参数定义线程调用的方法。

Thread t = new Thread(new ThreadStart(Go));//public static GO(){}


有兴趣的同学可以看下我之前写的多线程的博客:《C#多线程之旅(2):创建和开始线程》

b.设计模式中的简单工厂模式。

向一个方法中传递一个子类的方法。

c.事件。

一般通知代码发生了什么事件。GUI编程主要处理事件。在引发事件时,运行库需要知道应执行哪个方法。

这就需要处理事件的方法作为一个参数传递给委托。

4.如何自定义委托★☆

声明一个委托类型,它的实例引用一个方法,该方法获取一个int参数,返回void。

public delegate void Feedback(int num);

理解委托的一个要点是它们的安全性非常高。在定义委托时,必须给出它所表示的方法的签名和返回类型等全部细节。

理解委托的一种比较好的方式是把委托当作这样一件事情:它给方法的签名和返回类型指定名称。

其语法类似于方法的定义,需要在定义方法的前面加上delegate关键字。定义委托基本上就是定义一个新的类,所以可以在任何地方定义类的相同地方定义委托,也就是说,可以在另一个类的内部定义,也可以在任何类的外部定义,还可以在名称控件中把委托定义为定义为顶层对象。访问修饰符可以是public/private/protected等。

5..NET默认的委托类型有哪几种?★★

1.Action

  • 泛型Action委托表示引用一个void返回类型的方法。这个委托类存在16种重载方法。

  • 例如Action调用没有参数的方法

2.Func

  • Func调用带返回类型的方法。有16种重载方法。

  • 例如Func委托类型可以调用带返回类型且无参数的方法,Func委托类型调用带有4个参数和一个返回类型的方法。

3.等等

6.怎样使用委托★★


下面我将会用个例子来讲述怎样使用委托

// 声明一个委托类型,它的实例引用一个方法,该方法获取一个int参数,返回string

public delegate String myMethodDelegate(int myInt);

// 定义一些方法给委托变量引用

public class mySampleClass

{

        // 定义一个实例方法

        public String myStringMethod(int myInt)

        {

            if (myInt > 0)

                return (“positive”);

            if (myInt < 0)

                return (“negative”);

            return (“zero”);

        }

        // 定义一个静态方法

        public static String mySignMethod(int myInt)

        {

            if (myInt > 0)

                return (“+”);

            if (myInt < 0)

                return (“-“);

            return (“”);

        }

}

public static void Main()

{

        // 给每个方法都创建一个委托实例

        // 对于实例方法,mySC必须提供

        //   对于静态方法,只需要指定类的名字

        mySampleClass mySC = new mySampleClass();

        myMethodDelegate myD1 = new myMethodDelegate(mySC.myStringMethod);

        myMethodDelegate myD2 = new myMethodDelegate(mySampleClass.mySignMethod);

        // 调用委托

        Console.WriteLine(“{0} is {1}; use the sign \”{2}\”.”, 5, myD1(5), myD2(5));

        Console.WriteLine(“{0} is {1}; use the sign \”{2}\”.”, -3, myD1(-3), myD2(-3));

        Console.WriteLine(“{0} is {1}; use the sign \”{2}\”.”, 0, myD1(0), myD2(0));

}

输出

5 is positive; use the sign “+”.

-3 is negative; use the sign “-“.

0 is zero; use the sign “”.

7.多播委托是什么?★★★

包含多个方法的委托叫做多播委托。如果调用多播委托,就可以顺序连续调用多个方法。

为此,委托的签名就必须返回void;否则,就只能得到委托调用的最后一个方法的结果。

例子:

        /// 定义委托类型

        ///

        ///

        /// void

        public delegate void Feedback(int num);

         

        ///

        /// 实例方法

        ///

        ///

        /// void

        public void InstanceMethod(int a)

        {

            Console.WriteLine(a.ToString());

        }

        ///

        /// 静态方法

        ///

        ///

        /// 返回void

        public static void StaticMethod( int b)

        {

            Console.WriteLine((b * b).ToString());

        }

         

        //定义一个Program实例

        Program p = new Program();

        //委托feedback1指定回调方法:p.InstanceMethod

        Feedback feedback1 = new Feedback(p.InstanceMethod);

        //委托feedback2指定回调方法:StaticMethod

        Feedback feedback2 = new Feedback(StaticMethod);

        //输出2

        feedback1(2);

        //输出4

        feedback2(2);

         

        //—-多播委托——-

        Feedback fbChain = null;

        //将feedback1添加到fbChain委托中

        fbChain += feedback1;

        //将feedback2添加到fbChain委托中

        fbChain += feedback2;

        //输出:

        //2

        //4

        fbChain(2);

8.什么是泛型委托?★★★

比如第5题提到的,Action就是泛型委托。

注意事项:

1.建议尽量使用这些委托类型,而不是在代码中定义更多的委托类型。这样可以减少系统中的类型数目,同时简化编码

2.如果需要使用ref或out关键字,以传引用的方式传递一个参数,就可能不得不定义自己的委托:

delegate void Test(ref int i)


3.如果委托要通过C#的params关键字获取可变数量的额参数,要为委托的任何桉树指定默认值,或者要对委托的泛型类型参数进行约束,也必须定义自己的委托类型

delegate void EventHandler(Object sender, TEventArgs e)

where TEventArgs : EventArgs;


4.使用获取泛型实参和返回值的委托时,可利用逆变与协变。逆变:父类转换为子类;协变:子类转换为父类

9.什么事匿名方法★★

匿名方法是用作委托的参数的一段代码。

//匿名方法,例1

Func anon = delegate(int i)

{

        i = i+1;

       return i;

};

//输出2

Console.WriteLine(anon(1));

//匿名方法,例2

Action anon2 = delegate(int i)

{

        i = i + 1;

};

//输出2

Console.WriteLine(anon(1));

10.委托是否可以回调实例方法★★★

可以。委托可以回调实例方法和静态方法。如果是实例方法,委托需要知道方法操作的是哪个对象实例。

11.Lambda表达式是什么?★

从C#3.0开始,就可以使用一种新语法把实现代码赋予委托:Lambda表达式。

只要有委托参数类型的地方,就可以使用Lambda表达式。

12.Lambda表达式怎么传参?★★★

Lambda表达式有几种定义参数的方式。

1.只有一个参数,只写出参数名就足够了。

如下面的例子:定义了一个泛型委托,输入参数是一个string类型,返回一个string类型,lambda表达式:s=>s.Replace(‘a,b’)

委托引用的方法名:oneParam

传入参数:abc

打印结果:bbc

 Func oneParam = s => s.Replace(‘a’, ‘b’);

 Console.WriteLine(oneParam(“abc”));

 Console.ReadKey();

2.如果委托使用多个参数,就把参数名放在小括号中。

如下面的例子:定义了一个泛型委托,输入参数是两个int类型(可以给小括号中的变量名添加参数类型),返回一个int类型,lambda表达式:(i, j) => i*j

委托引用的方法名:twoParam

传入参数:2和4

打印结果:8

Func twoParam = (i, j) => i*j;

Console.WriteLine(twoParam(2,4));

13.Lambda多行代码怎么写?★★

添加大括号,如果需要返回值,则必须添加return语句

Func test = (i, j) => 

    i = i + 1;

    i = i * j;

    return i;

};

Console.WriteLine(test(2, 4));

打印结果:12

14.什么是闭包?★★

通过Lambda表达式可以访问Lambda表达式块外部的变量,这成为闭包。

当引用外部变量时,需要注意,外部变量变化时,lambda表达式的结果也可能会随着外部变量变化而变化。

如下面的例子:

int y = 5;

Func lambda = x => x + y;

Console.WriteLine(lambda(1));

y = 10;

Console.WriteLine(lambda(1));

第一次打印出6,第二次打印出11

写在最后

关于委托的知识点还有很多没有总结出来,比如说委托和反射,委托的底层实现等等。面试经常会问到也就是上面总结的。

看完本文有收获?请转发分享给更多人

关注「DotNet」,提升.Net技能 

转载请注明:CodingBlog » 不惧面试:.NET编程之委托

喜欢 (0)or分享 (0)
发表我的评论
取消评论

*

表情
(4)个小伙伴在吐槽
  1. 总结的很棒
    马里奥的马里奥2017-02-16 04:21 回复
  2. 总结的很好,比较全面
    飞翔企鹅2017-02-16 07:28 回复
  3. 委托,lambda都是很好用的,委托能做得事太多了,
    Mr_Dong2017-02-16 10:53 回复
  4. 怀疑作者懂不懂闭包,同样怀疑的请点右上角。
    牛啵霸王2017-02-16 12:28 回复