-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathclosures-in-csharp.html
233 lines (198 loc) · 13.4 KB
/
closures-in-csharp.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=Edge"/>
<title>Warren Bates - Closures in C#</title>
<meta name="description" content="Warren Bates" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link type="application/rss+xml" rel="alternate" title="Warren Bates" href="/feed.rss" />
<link type="application/atom+xml" rel="alternate" title="Warren Bates" href="/feed.atom" />
<link rel="shortcut icon" href="/favicon.ico" type="image/x-icon">
<link rel="icon" href="/favicon.ico" type="image/x-icon">
<link href="/assets/css/bootstrap.min.css" rel="stylesheet" />
<link href="/assets/css/highlight.css" rel="stylesheet">
<link href="/assets/css/clean-blog.css" rel="stylesheet" />
<link href="/assets/css/master.css" rel="stylesheet" />
<link href="/assets/css/font-awesome.min.css" rel="stylesheet" type="text/css">
<link href='//fonts.googleapis.com/css?family=Lora:400,700,400italic,700italic' rel='stylesheet' type='text/css'>
<link href='//fonts.googleapis.com/css?family=Open+Sans:300italic,400italic,600italic,700italic,800italic,400,300,600,700,800' rel='stylesheet' type='text/css'>
<link href="/assets/css/override.css" rel="stylesheet" />
<meta name="application-name" content="Warren Bates" />
<meta name="msapplication-tooltip" content="Warren Bates" />
<meta name="msapplication-starturl" content="/" />
<meta property="og:title" content="Warren Bates - Closures in C#" />
<meta property="og:type" content="website" />
<meta property="og:url" content="https://wbates.net/posts/closures-in-csharp" />
<!-- TODO: More social graph meta tags -->
<script src="/assets/js/jquery.min.js"></script>
<script src="/assets/js/bootstrap.min.js"></script>
<script src="/assets/js/highlight.pack.js"></script>
<script src="/assets/js/clean-blog.js"></script>
<script src="/assets/js/d3.v3.min.js"></script>
<script src="/assets/js/trianglify.min.js"></script>
<script src="/assets/js/Please-compressed.js"></script>
<script src="/assets/js/background-check.min.js"></script>
<!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
<!--[if lt IE 9]>
<script src="/assets/js/html5shiv.js"></script>
<script src="/assets/js/respond.min.js"></script>
<![endif]-->
</head>
<body>
<!-- Navigation -->
<nav class="navbar navbar-default navbar-custom navbar-fixed-top">
<div class="container-fluid">
<!-- Brand and toggle get grouped for better mobile display -->
<div class="navbar-header page-scroll">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#navbar-collapse">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="/">Warren Bates</a>
</div>
<!-- Collect the nav links, forms, and other content for toggling -->
<div class="collapse navbar-collapse" id="navbar-collapse">
<ul class="nav navbar-nav navbar-right">
<li><a href="/posts">Archive</a></li>
<li><a href="/tags">Tags</a></li>
<li><a href="/about">About Me</a></li>
</ul>
</div>
<!-- /.navbar-collapse -->
</div>
<!-- /.container -->
</nav>
<!-- Page Header -->
<header class="intro-header" id="intro-header">
<div class="container">
<div class="row">
<div class="col-md-12">
<div class="post-heading">
<h1>Closures in C#</h1>
<div class="meta">
Published on 28 May 2015<br> </div>
<div class="tags">
<a role="button" href="/tags/C%23" class="btn btn-default btn-xs">C#</a>
<a role="button" href="/tags/Closures" class="btn btn-default btn-xs">Closures</a>
<a role="button" href="/tags/CSharp" class="btn btn-default btn-xs">CSharp</a>
<a role="button" href="/tags/Euler-Problems" class="btn btn-default btn-xs">Euler Problems</a>
<a role="button" href="/tags/JavaScript" class="btn btn-default btn-xs">JavaScript</a>
<a role="button" href="/tags/Prime-numbers" class="btn btn-default btn-xs">Prime numbers</a>
</div>
</div>
</div>
</div>
</div>
</header>
<!-- Main Content -->
<div class="container">
<div class="row">
<div id="content" class="col-md-12">
<p>Closures are a vital part of any language that passes functions around as variables. They ensure that everything that was available when we defined the function is available when it's called later, even if it's called in a different scope or long after the original scope has completely ended. There's a vast amount of information available on closures in Javascript because as a classless language where functions are always first class objects closures are regularly used to imitate class like functionality.</p>
<p>For example:</p>
<pre><code class="language-javascript">function fakeClass() {
var publicVar = "This variable will be public";
this.publicVar = publicVar;
var privateVar = "This variable will be private";
this.getPrivateVar = function() {
return privateVar;
}
}
var instance = new fakeClass();
// This will output "This variable will be public"
console.log(instance.publicVar);
// This will output "This variable will be private"
console.log(instance.getPrivateVar());
// This will throw a type undefined error
console.log(instance.privateVar);
</code></pre>
<p>In the above code the publicVar variable is attached to the this object and can be set and read through accessing fakeClass.publicVar. However, the privateVar variable cannot be accessed since it has not been attached to the this object. That is where the getPrivateVar function comes in. The privateVar variable was available at the time the function was defined and so it will be available when the getPrivateVar function is called. The privateVar itself is no longer in scope at the bottom of the example and since it wasn't attached to the this object when we try to access it, we'll get an error.</p>
<p>This is just an example of how closures can be used and what they do. In C# we obviously have far better ways of declaring private variables, namely the private keyword. That's not to say that closures are suddenly useless in C#, in fact any time we want a function to have data that persists between uses we can use a closure to do so. The alternative would be to create a class that contains properties for all of the data we want to use, but closures are much briefer in terms of how much code is needed.</p>
<h1 id="prime-generator">Prime Generator</h1>
<p>For the Project Euler problems I realised I was needing to copy code between problems and one of the things I was regularly doing was generating prime numbers. Doing so with a normal function would require that I knew how many primes I needed, and could then return an array with all of the primes up to that point. .Net's IEnumerable achieves something very similar to this; closures are just another tool in the box. I like how simple they are to write and use, but sometimes we may need the more advanced functionality of the IEnumerable.
The pseudo code for generating prime numbers looks something like the following, where isPrime(num) is a function which returns a boolean telling us if the num variable passed is a prime number or not (more notes on that at the end).</p>
<pre><code>private int getPrime() {
int current = 2;
while (true) {
if (isPrime(current)) {
return current;
}
current++;
}
}
</code></pre>
<p>You've possibly already spotted the problem. As soon as a prime is found, which is immediately since we start with a prime, the function will return and the current variable will never get incremented. The next time the function is called the current value will once again be set as 2 and will be returned immediately. Enter the closure.</p>
<p>What if we could put the while loop into a separate function that incremented the current value? We first need to change the above function so that it returns a delegate function. Making a function a delegate means it can be passed around like a variable in the same way as all functions can be in javascript.</p>
<p>The function declaration needs to be changed to <code>private Func\<int\> getPrimeGenerator()</code>. This tells the compiler that we will be expecting the return from this function to be a delegate function which itself has a return type of int. Next we declare and initialise the variable that stores our current position, then we declare the function that will return our primes.</p>
<pre><code class="language-csharp">private Func<int> getPrimes()
{
int current = 1;
Func<int> nextPrime = delegate()
{
current++;
while (!isPrime(current))
{
current++;
}
return current;
};
return nextPrime;
}
</code></pre>
<p>The pseudo code has been modified slightly so that the if statement has been implemented with the while loop, but the functionality isn't any different. Each time the delegate function is called it will increment the current variable until a new prime is found and return that. A reference to the current variable has been closed into the delegate function. Let's see how this is used to get the first hundred prime numbers.</p>
<pre><code class="language-csharp">var getNextPrime = getPrimes();
for (int i = 0; i < 100; i++) {
Console.WriteLine(getNextPrime());
}
</code></pre>
<p>That's it. We call the first function and store the returned delegate in another variable, then we call that as many times as we like, each time it will return the next prime number that can be found. Eventually this code will hit the maximum value for an integer and will go back to the beginning, but dealing with that is left as an exercise for the reader.</p>
</div>
</div>
</div>
<hr>
<!-- Footer -->
<footer>
<div class="container">
<div class="row">
<div class="col-md-12 text-center">
<p class="copyright text-muted">
Copyright © 2018
<br />
<a href="/feed.rss"><i class="fa fa-rss"></i> RSS Feed</a>
|
<a href="/feed.atom"><i class="fa fa-rss"></i> Atom Feed</a>
<br />
<strong><a href="https://wyam.io">Generated by Wyam</a></strong>
</p>
</div>
</div>
</div>
</footer>
<script>hljs.initHighlightingOnLoad();</script>
<script type="text/javascript">
// Header background
var colors = Please.make_color({
colors_returned: 3,
saturation: .6
});
var t = new Trianglify({
x_gradient: colors,
y_gradient: ["#FFFFFF"]
});
var header = document.getElementById("intro-header");
var pattern = t.generate(header.clientWidth, header.clientHeight);
header.setAttribute('style', 'background-image: ' + pattern.dataUrl);
</script>
<script>
BackgroundCheck.init({
targets: '.intro-header,.navbar',
images: '.intro-header'
});
</script>
</body>
</html>