亲宝软件园·资讯

展开

解析“60k”大佬的19道C#面试题(下)

.NET骚操作 人气:0
# 解析“60k”大佬的19道C#面试题(下) 在上篇中,我解析了前 `10` 道题目,本篇我将尝试解析后面剩下的所有题目。 > 姐妹篇:[解析“60k”大佬的19道C#面试题(上)](https://www.cnblogs.com/sdflysha/p/20200325-19-csharp-interview-question-from-60k-boss-1.html) 这些题目确实不怎么经常使用,因此在后文中,我会提一组我的私房经典“`6k`面试题”,供大家轻松一刻。 ## 先略看题目: 11. 简述 `LINQ` 的 `lazy computation` 机制 12. 利用 `SelectMany` 实现两个数组中元素做笛卡尔集,然后一一相加 13. 请为三元函数实现柯里化 14. 请简述 `ref struct` 的作用 15. 请简述 `ref return` 的使用方法 16. 请利用 `foreach` 和 `ref` 为一个数组中的每个元素加 `1` 17. 请简述 `ref` 、 `out` 和 `in` 在用作函数参数修饰符时的区别 18. 请简述非 `sealed` 类的 `IDisposable` 实现方法 19. `delegate` 和 `event` 本质是什么?请简述他们的实现机制 # 解析: ## 11. 简述 `LINQ` 的 `lazy computation` 机制 `Lazy computation` 是指延迟计算,它可能体现在**解析阶段**的**表达式树**和**求值阶段**的**状态机**两方面。 首先是**解析阶段**的**表达式树**, `C#` 编译器在编译时,它会将这些语句以表达式树的形式保存起来,在求值时, `C#` 编译器会将所有的 `表达式树` 翻译成求值方法(如在数据库中执行 `SQL` 语句)。 其次是**求值阶段**的**状态机**, `LINQ to Objects` 可以使用像 `IEnumemrable` 接口,它本身不一定保存数据,**只有在求值时**,它返回一个迭代器—— `IEnumerator` ,它才会根据 `MoveNext()` / `Value` 来求值。 这两种机制可以确保 `LINQ` 是可以延迟计算的。 ## 12. 利用 `SelectMany` 实现两个数组中元素做笛卡尔集,然后一一相加 ``` csharp // 11. 利用 `SelectMany` 实现两个数组中元素的两两相加 int[] a1 = { 1, 2, 3, 4, 5 }; int[] a2 = { 5, 4, 3, 2, 1 }; a1 .SelectMany(v => a2, (v1, v2) => $"{v1}+{v2}={v1 + v2}") .Dump(); ``` 解析与说明:大多数人可能只了解 `SelectMany` 做一转多的场景(两参数重载,类似于 `flatMap` ),但它还提供了这个三参数的重载,可以允许你做多对多——笛卡尔集。因此这些代码实际上可以用如下 `LINQ` 表示: ``` csharp from v1 in a1 from v2 in a2 select $"{v1}+{v2}={v1 + v2}" ``` 执行效果完全一样。 ## 13. 请为三元函数实现柯里化 解析:柯里化是指将 `f(x, y)` 转换为 `f(x)(y)` 的过程,三元和二元同理: ``` csharp Func op3 = (a, b, c) => (a - b) * c; Func>> op11 = a => b => c => (a - b) * c; op3(4, 2, 3).Dump(); // 6 op11(4)(2)(3).Dump(); // 6 ``` 通过实现一个泛型方法,实现**通用的**三元函数柯里化: ``` csharp Func>> Currylize3(Func op) { return a => b => c => op(a, b, c); } // 测试代码: var op12 = Currylize3(op3); op12(4)(2)(3).Dump(); // (4-2)x3=6 ``` > 现在了解为啥 `F#` 签名也能不用写参数了吧,因为参数确实太长了

加载全部内容

相关教程
猜你喜欢
用户评论