C#面试题(三)(包含答案)

1.System.Linq 对迭代器进行操作

     首先了解Linq的简单操作 : LINQ 查询函数整理

            DataClasses1DataContext db = new DataClasses1DataContext();
            var q =
                  (from c in db.Customers
                  select new
                  {
                      c.CustomerID,
                      CompanyInfo = new { c.CompanyName, c.City, c.Country },
                      ContactInfo = new { c.ContactName, c.ContactTitle }
                  }).ToList();
            foreach (var d in q)
            {
                //Response.Write(d.CompanyInfo);
                foreach (IEnumerable<string> str in d.CompanyInfo)
                {
                    Response.Write(str);
                }
                
            }

2.System.Action / UnityAction / System.Func

  Action委托引用了一个void返回类型的方法,T表示方法参数,先看Action委托有哪些
Action Action<in T>
Action<in T1,in T2>
Action<in T1,in T2 .... inT16>

//action可以后面通过泛型去指定action指向的方法的多个参数的类型 ,参数的类型跟action后面声明的委托类型是对应着的

Action a = PrintString;//action是系统内置(预定义)的一个委托类型,它可以指向一个没有返回值,没有参数的方法
Action<int> a = PrintInt;//定义了一个委托类型,这个类型可以指向一个没有返回值,有一个int参数的方法
Action<string> a = PrintString;//定义了一个委托类型,这个类型可以指向一个没有返回值,有一个string参数的方法 在这里系统会自动寻找匹配的方法
Action<int, int> a = PrintDoubleInt;//多个参数,指向两个int参数的无返回值的函数

Func引用了一个带有一个返回值的方法,它可以传递0或者多到16个参数类型,和一个返回类型
Func<out TResult>
Func<in T,out TResult>
Func<int T1,inT2,,,,,,in T16,out TResult>
Func<int> a = Test1;//func中的泛型类型指定的是 方法的返回值类型
Func<string, int> a = Test2;//func后面可以跟很多类型,最后一个类型是返回值类型,前面的类型是参数类型,参数类型必须跟指向的方法的参数类型按照顺序对应
Func<int, int, int> a = Test3;//func后面必须指定一个返回值类型,参数类型可以有0-16个,先写参数类型,最后一个是返回值类型
int res = a(1, 5);


事件(Event)是类或对象向其他类或对象通知发生的事情的一种特殊签名的委托.
在类的内部声明事件,首先必须声明该事件的委托类型。例如:
             public delegate void BoilerLogHandler(string status);然后,声明事件本身,使用 event 关键字:
// 基于上面的委托定义事件
             public event BoilerLogHandler BoilerEventLog;

3.链式编程  

4.callback

       首先来了解一下 程序的健壮性和鲁棒性

       如何采取一定措施保证回调编程的鲁棒性?笔者才疏学浅,如果有知道的大佬,请动动手指留下你的解答~

Callback(同步回调) :

    原型如下 : 

public delegate void CallBack();
public delegate void CallBack<T>(T t);
public delegate void CallBack<T, V>(T t, V v);
public delegate void CallBack<T, V, U>(T t, V v, U u);

   使用方法:

 CallBack callBack = test;
  public void test()
    {

    }

AsyncCallback(异步回调)的使用:

(1)BeginInvoke方法可启动异步调用。

(2)EndInvoke方法检索异步调用的结果。

扫描二维码关注公众号,回复: 2710293 查看本文章

(3)AsyncCallback委托用于指定在开始操作完成后应被调用的方法

(4)IAsyncResult接口 : 它表示异步操作的状态.该接口定义了4个公用属性。

    使用方法:

        public static void DemoCallback()
        {
            MethodDelegate dlgt = new MethodDelegate(LongRunningMethod);
            int iExecThread;
            AsyncCallback asyncCallback = new AsyncCallback(MyAsyncCallback);
            IAsyncResult iar = dlgt.BeginInvoke(5000,out iExecThread, asyncCallback, dlgt);
        }
 
        /// <summary>
        ///  异步方法完成后执行回调
        /// </summary>
        /// <param name="iar"></param>
        public static void MyAsyncCallback(IAsyncResult iar)
        {
            string str;
            int iExecThread;
            MethodDelegate dlgt = (MethodDelegate)iar.AsyncState;
            str = dlgt.EndInvoke(out iExecThread, iar);
            Console.WriteLine("the Delegate call returned string:{0},and the number is:{1}", str, iExecThread.ToString());
        }
     参考链接 : 异步编程(AsyncCallback委托,IAsyncResult接口,BeginInvoke方法,EndInvoke方法的使用小结)
        

5.递归

     任何一个方法既可以调用其他方法又可以调用自己,而当这个方法调用自己时,我们就叫它递归函数或者递归方法! 
     举例(计算阶乘) :
 pubic long Factorial(int n){
  
  if(n==0){  
    return 1;  
   }
    return n*Factorial(n-1);  
 }
       堆栈溢出的问题:
          函数调用的参数是通过栈空间来传递的,在调用过程中会占用线程的栈资源。而递归调用,只有走到最后的结束点后函数才能依次退出,而未到达最后的结束点之前,占用的栈空间一直没有释放,如果递归调用次数过多,就可能导致占用的栈资源超过线程的最大值,从而导致栈溢出,导致程序的异常退出.
解决方案:

           1)project property->Configuration Properties->Linker->System->Stack Reserve Size改成10000000,注意是7个0

           2)  将数组改成指针,然后用new或malloc在heap中动态分配。

           3)用栈加while循环代替递归

①、定义一个新的结构体StructA,用于保存递归结构中的一些数据和状态信息。

在StructA内部需要包含的变量有以下几种:

  1) 一般当递归函数调用自身时,函数参数会发生变化。所以你需要包含变化的参数,引用除外;

  2) 阶段性变量"Stage"(通常是一个用来转换到另一个处理分支的整形变量);

  3) 函数调用返回以后还需要继续使用的局部变量。   

     struct StructA{

        int ParamA,ParamB;     //变化的递归函数的参数     

        int ReturnLocal;           //函数调用返回后还需继续使用的局部变量

        int Stage;     

      };

②、创建函数。

                 

     参考 : 1.C#递归

               2.递归调用出现堆栈溢出的解决方案

猜你喜欢

转载自blog.csdn.net/dengshunhao/article/details/81035712