胡乱写的一点利用C#中闭包模拟OOP的代码

先来看一段JS代码:

function Outer()
{
 var count = 0;
 var Inner = function(){
  alert(count++);
 }
 return Inner;
}

var f = Outer();
var k = Outer();
f();
f();
k();
f();
k();

这就是JS中最简单的闭包实现,可以类似对象的操作,以函数的形式内聚一些数据.

我们知道C#中是支持闭包的,一个方法(函数)引用了其作用域以外的变量,进行操作.具体实现原理可以自己用IL或者找些文章来了解.

那如果一个OOP的语言,使用FP的特性,再来模拟出OOP的特性,那真是吃饱了撑的,不过肯定好玩.

今天学习了这篇文章 http://www.cnblogs.com/weidagang2046/archive/2010/11/01/1865899.html,照葫芦画瓢写了几行代码,全为了加深理解.

先写一个最简单的类

代码1
1 public class OOPer
2 {
3 private int count = 0;
4
5 public void Say()
6 {
7 Console.WriteLine(count++);
8 }
9
10 public void Reset()
11 {
12 count = 0;
13 Console.WriteLine("Have Reset");
14 }
15
16 public void Set(int newcount)
17 {
18 count = newcount;
19 Console.WriteLine("Set");
20 }
21 }

你可以实现此类若干事例,不断调用Say,Set,Reset方法。那如果使用闭包的形式会是怎样的?

代码2
1 public class FPer
2 {
3 Func<FPerMethod, object> fpfunc = null;
4
5 public FPer()
6 {
7 fpfunc = GetClosure();
8 }
9
10 public void Say()
11 {
12 Action act = fpfunc(FPerMethod.Say) as Action;
13 act();
14 }
15
16 public void Reset()
17 {
18 Action act = fpfunc(FPerMethod.Reset) as Action;
19 act();
20 }
21
22 public void Set(int newcount)
23 {
24 Action<int> act = fpfunc(FPerMethod.Set) as Action<int>;
25 act(newcount);
26 }
27
28 private enum FPerMethod
29 {
30 Say,
31 Reset,
32 Set
33 }
34
35 /// <summary>
36 /// 使用不同的枚举类型作为参数,选择返回不同的操作方法
37 /// </summary>
38 /// <returns></returns>
39   private Func<FPerMethod, object> GetClosure()
40 {
41 int count = 0;
42
43 Func<FPerMethod, object> func =
44 (method) =>
45 {
46 if (method == FPerMethod.Say)
47 {
48 Action act = () => { Console.WriteLine(count++); };
49 return act;
50 }
51 else if (method == FPerMethod.Reset)
52 {
53 Action act = () =>
54 {
55 count = 0;
56 Console.WriteLine("Have Reset");
57 };
58 return act;
59 }
60 else if (method == FPerMethod.Set)
61 {
62 Action<int> act = (c) =>
63 {
64 count = c;
65 Console.WriteLine("Set");
66 };
67
68 return act;
69 }
70
71 return null;
72 };
73
74 return func;
75 }
76 }

使用方式和OOper一模一样,只要new一个FPer,就可以使用了。其核心就是GetClosure(),相当于一个FactoryMothed,每次Create一个用闭包是实现的特殊对象,又像是一个对象,因为你所使用核心数据count也是在它的作用域中。所以,如果你把 Action act = fpfunc(FPerMethod.Say) as Action;换成了Action act = GetClosure()(FPerMethod.Say) as Action;所得的结果就不会是现在这样了。

原文地址:https://www.cnblogs.com/apodemakeles/p/1866256.html