解析“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#` 签名也能不用写参数了吧,因为参数确实太长了
加载全部内容
- 猜你喜欢
- 用户评论