金三银四面试:C#.NET面试题中高级篇3,含答案解析

2022-04-19 08:50:41 浏览数 (1)

目录

  1. 利用IEnumerable实现斐波那契数列生成?

2.请利用 foreach 和 ref 为一个数组中的每个元素加 1

3.如何针对不同的异常进行捕捉?

4.如何避免类型转换时的异常?

5.Serializable特性在.NET中有什么作用?

6.在.NET中的委托是什么?

7.在.NET中可以自定义委托吗?

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

9.什么是泛型委托?

10. 什么是匿名方法?

1.利用IEnumerable实现斐波那契数列生成?

代码语言:javascript复制
  IEnumerable<int> GenerateFibonacci(int n)
{
    if (n >= 1) yield return 1;

    int a = 1, b = 0;
    for (int i = 2; i <= n;   i)
    {
        int t = b;
        b = a;
        a  = t;
        yield return a;
    }
}

---->详解

2.请利用 foreach 和 ref 为一个数组中的每个元素加 1 注意 foreach 不能用 var ,也不能直接用 int ,需要 ref int ,注意 arr 要转换为 Span 。

代码语言:javascript复制
int[] arr = { 1, 2, 3, 4, 5};
Console.WriteLine(string.Join(",", arr)); // 1,2,3,4,5

foreach (ref int v in arr.AsSpan())
{
    v  ;
}

Console.WriteLine(string.Join(",", arr)); // 2,3,4,5,6

---->详解3.如何针对不同的异常进行捕捉?

代码语言:javascript复制
  public class Program
    {
        public static void Main(string[] args)
        {
            Program p = new Program();
            p.RiskWork();

            Console.ReadKey();
        }

        public void RiskWork()
        {
            try
            {
                // 一些可能会出现异常的代码
            }
            catch (NullReferenceException ex)
            {
                HandleExpectedException(ex);
            }
            catch (ArgumentException ex)
            {
                HandleExpectedException(ex);
            }
            catch (FileNotFoundException ex)
            {
                HandlerError(ex);
            }
            catch (Exception ex)
            {
                HandleCrash(ex);
            }
        }

        // 这里处理预计可能会发生的,不属于错误范畴的异常
        private void HandleExpectedException(Exception ex)
        {
            // 这里可以借助log4net写入日志
            Console.WriteLine(ex.Message);
        }

        // 这里处理在系统出错时可能会发生的,比较严重的异常
        private void HandlerError(Exception ex)
        {
            // 这里可以借助log4net写入日志
            Console.WriteLine(ex.Message);
            // 严重的异常需要抛到上层处理
            throw ex; 
        }

        // 这里处理可能会导致系统崩溃时的异常
        private void HandleCrash(Exception ex)
        {
            // 这里可以借助log4net写入日志
            Console.WriteLine(ex.Message);
            // 关闭当前程序
            System.Threading.Thread.CurrentThread.Abort();
        }
    }

--->详解4.如何避免类型转换时的异常?其中有些是确定可以转换的(比如将一个子类类型转为父类类型),而有些则是尝试性的(比如将基类引用的对象转换成子类)。当执行常识性转换时,我们就应该做好捕捉异常的准备。当一个不正确的类型转换发生时,会产生InvalidCastException异常,有时我们会用try-catch块做一些尝试性的类型转换,这样的代码没有任何错误,但是性能却相当糟糕,为什么呢?异常是一种耗费资源的机制,每当异常被抛出时,异常堆栈将会被建立,异常信息将被加载,而通常这些工作的成本相对较高,并且在尝试性类型转换时,这些信息都没有意义。在.NET中提供了另外一种语法来进行尝试性的类型转换,那就是关键字 is 和 as 所做的工作。(1)is 只负责检查类型的兼容性,并返回结果:true 和 false。→ 进行类型判断两者的共同之处都在于:不会抛出异常!综上比较,as 较 is 在执行效率上会好一些,在实际开发中应该量才而用,在只进行类型判断的应用场景时,应该多使用 is 而不是 as。

代码语言:javascript复制
  public static void Main(string[] args)
    {
        object o = new object();
        // 执行类型兼容性检查
        if(o is ISample)
        {
            // 执行类型转换
            ISample sample = (ISample)o;
            sample.SampleShow();
        }

        Console.ReadKey();
    }

(2)as 不仅负责检查兼容性还会进行类型转换,并返回结果,如果不兼容则返回 null 。→ 用于类型转型

代码语言:javascript复制
  public static void Main(string[] args)
    {
        object o = new object();
        // 执行类型兼容性检查
        ISample sample = o as ISample;
        if(sample != null)
        {
            sample.SampleShow();
        }
        Console.ReadKey();
    }

两者的共同之处都在于:不会抛出异常!综上比较,as 较 is 在执行效率上会好一些,在实际开发中应该量才而用,在只进行类型判断的应用场景时,应该多使用 is 而不是 as。

5.Serializable特性在.NET中有什么作用?通过上面的流类型可以方便地操作各种字节流,但是如何把现有的实例对象转换为方便传输的字节流,就需要使用序列化技术。对象实例的序列化,是指将实例对象转换为可方便存储、传输和交互的流。在.NET中,通过Serializable特性提供了序列化对象实例的机制,当一个类型被申明为Serializable后,它就能被诸如BinaryFormatter等实现了IFormatter接口的类型进行序列化和反序列化。6.在.NET中的委托是什么?委托是寻址的.NET版本。在C 中,函数指针只不过是一个指向内存位置的指针,它不是类型安全的。我们无法判断这个指针实际指向什么,像参数和返回类型等项久更无从知晓了。而.NET委托完全不同,委托是类型安全的类,它定义了返回类型和参数的类型。委托类不仅包含对方法的引用,也可以包含对多个方法的引用。---->详解7.在.NET中可以自定义委托吗?声明一个委托类型,它的实例引用一个方法,该方法获取一个int参数,返回void。

代码语言:javascript复制
  public delegate void Feedback(int num);

理解委托的一个要点是它们的安全性非常高。在定义委托时,必须给出它所表示的方法的签名和返回类型等全部细节。 理解委托的一种比较好的方式是把委托当作这样一件事情:它给方法的签名和返回类型指定名称。其语法类似于方法的定义,需要在定义方法的前面加上delegate关键字。定义委托基本上就是定义一个新的类,所以可以在任何地方定义类的相同地方定义委托,也就是说,可以在另一个类的内部定义,也可以在任何类的外部定义,还可以在名称控件中把委托定义为定义为顶层对象。访问修饰符可以是public/private/protected等。---->详解8 .NET默认的委托类型有哪几种?

1)Action < T >泛型Action委托表示引用一个void返回类型的方法。这个委托类存在16种重载方法。例如Action<in T1,In T2>调用没有参数的方法

2).Func< T >Func调用带返回类型的方法。有16种重载方法。

例如Func委托类型可以调用带返回类型且无参数的方法,Func<in T,out TResult>委托类型调用带有4个参数和一个返回类型的方法。---->详解

9.什么是泛型委托?

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).使用获取泛型实参和返回值的委托时,可利用逆变与协变。逆变:父类转换为子类;协变:子类转换为父类

---->详解

10. 什么是匿名方法?

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

代码语言:javascript复制
  //匿名方法,例1
Func<int, int> anon = delegate(int i)
{
        i = i 1;
       return i;
};
//输出2
Console.WriteLine(anon(1));
//匿名方法,例2
Action<int> anon2 = delegate(int i)
{
        i = i   1;
};
//输出2
Console.WriteLine(anon(1));

---->详解

版权申明:本文来源于网友收集或网友提供,仅供学习交流之用,如果有侵权,请转告版主或者留言,本公众号立即删除。

0 人点赞