Closure |
Written by Mike James | ||||
Tuesday, 11 May 2010 | ||||
Page 2 of 3
Using closure 1 - More parametersClearly closures are fun but what use are they? The answer is that they provide a context for a function which can be used to provide it with additional information without the need to use additional parameters. Why wouldn’t you create some additional parameters? Most likely because the signature of the function you are trying to use isn’t under your control. For example consider the EnumWindows API call which needs a callback function that is called for each window that it enumerates. The API call is: [DllImport("user32.dll")] and the callback delegate is: public delegate bool EnumWindowsProc( The problem with using the callback delegate is that it only has the two parameters - the handle of the current window and a pointer supplied in the call to the EnumWindows function. It is this pointer that is used to communicate between the callback function and the program needing the enumeration. Closure, however, makes communication much easier. If you need a function to find a particular dialog box specified by its Owner and its Caption string then you could write a function something like: public IntPtr getDialog( Clearly we need to pass the Owner and Caption to the callback delegate so that it can compare each of the enumerated windows to the target. The most natural way to do this is to provide these extra pieces of information to the callback via extra parameters but to work as a callback it can only have the parameters defined by the API. The simplest solution is to define the callback delegate in the usual way but use the fact that the Owner and Caption parameters are in scope and so are captured by an anonymous function: EnumWindowsProc enumProc = First we get the window text and compare it to Caption, which we can only access here thanks to closure: int length = If they match we check that the class name is correct for a dialog box and then check that Owner, which is once again only accessible at this point because of closure, is the correct window: int max = 100; This completes the anonymous callback delegate; now we can call EnumWindows: IntPtr DlgHwnd = IntPtr.Zero; To follow what is going on here you need to keep in mind that the callback is actually run by the API via the call enumProc(handle,pointer);
which passes in the handle to the window and a pointer to soon additional data. The Owner and Caption variables are used within the callback courtesy of closure. Notice that the pointer in the callback delegate is used to return the handle of the dialog box that we have found but this too could have been achieved using closure. Without any use of closure we would have had to pack the Owner and Caption into a data structure and passed this to the callback. Closure makes things much simpler in this case. <ASIN:1430225491> <ASIN:0321718933> <ASIN:0470467274> <ASIN:0470563486> <ASIN:1430225254> |
||||
Last Updated ( Tuesday, 20 September 2016 ) |