Methods within methods
-
I just discovered how powerful concept is to have a method local to another method. For instance let's assume you have a function that lists the position of elements within a grid. For the sake of simplicity imagine a grid can only have either rows or columns (but not both). Here is what you can do: void PrintElements(Grid grid, bool isVertical) { Func getElementPosition = arg=> isVertical ? Grid.GetRow(arg) : Grid.GetColumn(arg); foreach (FrameworkElement element in grid.Children) { Console.WriteLine(getElementPosition(element)); } } Hence a local func is only visible within PrintElements and can be used in numerous occasions !
Ashish Kaila
-
I just discovered how powerful concept is to have a method local to another method. For instance let's assume you have a function that lists the position of elements within a grid. For the sake of simplicity imagine a grid can only have either rows or columns (but not both). Here is what you can do: void PrintElements(Grid grid, bool isVertical) { Func getElementPosition = arg=> isVertical ? Grid.GetRow(arg) : Grid.GetColumn(arg); foreach (FrameworkElement element in grid.Children) { Console.WriteLine(getElementPosition(element)); } } Hence a local func is only visible within PrintElements and can be used in numerous occasions !
Ashish Kaila
Yeeahh... anonymous methods? They can be a bit useful at times.
-
I just discovered how powerful concept is to have a method local to another method. For instance let's assume you have a function that lists the position of elements within a grid. For the sake of simplicity imagine a grid can only have either rows or columns (but not both). Here is what you can do: void PrintElements(Grid grid, bool isVertical) { Func getElementPosition = arg=> isVertical ? Grid.GetRow(arg) : Grid.GetColumn(arg); foreach (FrameworkElement element in grid.Children) { Console.WriteLine(getElementPosition(element)); } } Hence a local func is only visible within PrintElements and can be used in numerous occasions !
Ashish Kaila
what will be use?
-
I just discovered how powerful concept is to have a method local to another method. For instance let's assume you have a function that lists the position of elements within a grid. For the sake of simplicity imagine a grid can only have either rows or columns (but not both). Here is what you can do: void PrintElements(Grid grid, bool isVertical) { Func getElementPosition = arg=> isVertical ? Grid.GetRow(arg) : Grid.GetColumn(arg); foreach (FrameworkElement element in grid.Children) { Console.WriteLine(getElementPosition(element)); } } Hence a local func is only visible within PrintElements and can be used in numerous occasions !
Ashish Kaila
It kinda reminded me of local classes in C++, where you could create a class within a method (with certain restrictions). I always wondered how could they be used, until I read Alexandrescu's Modern C++ Design, where he pointed a particular use: create a class that implements certain interface, so you could have a factory-like method...
-
It kinda reminded me of local classes in C++, where you could create a class within a method (with certain restrictions). I always wondered how could they be used, until I read Alexandrescu's Modern C++ Design, where he pointed a particular use: create a class that implements certain interface, so you could have a factory-like method...
It's amazing how techniques etc that have been around for many, many years keep cropping up as though they were new - Pascal anyone? 8)
-
I just discovered how powerful concept is to have a method local to another method. For instance let's assume you have a function that lists the position of elements within a grid. For the sake of simplicity imagine a grid can only have either rows or columns (but not both). Here is what you can do: void PrintElements(Grid grid, bool isVertical) { Func getElementPosition = arg=> isVertical ? Grid.GetRow(arg) : Grid.GetColumn(arg); foreach (FrameworkElement element in grid.Children) { Console.WriteLine(getElementPosition(element)); } } Hence a local func is only visible within PrintElements and can be used in numerous occasions !
Ashish Kaila
The best thing about anonymous methods IMO is that you can pass them as parameters, which gives a couple of Async pattern options...
____________________________________________________________ Be brave little warrior, be VERY brave
-
It's amazing how techniques etc that have been around for many, many years keep cropping up as though they were new - Pascal anyone? 8)
I agree, there are times I miss those things, though barely remember how many years ago I saw Pascal for the last time. BTW, you can do the same tricks with anonymous inner classes, in Java...
-
I just discovered how powerful concept is to have a method local to another method. For instance let's assume you have a function that lists the position of elements within a grid. For the sake of simplicity imagine a grid can only have either rows or columns (but not both). Here is what you can do: void PrintElements(Grid grid, bool isVertical) { Func getElementPosition = arg=> isVertical ? Grid.GetRow(arg) : Grid.GetColumn(arg); foreach (FrameworkElement element in grid.Children) { Console.WriteLine(getElementPosition(element)); } } Hence a local func is only visible within PrintElements and can be used in numerous occasions !
Ashish Kaila
A shorter version which demonstrates the locality better is this:
void PrintElements(Grid grid, bool isVertical)
{
foreach (FrameworkElement element in grid.Children) {
Console.WriteLine(arg => isVertical ? Grid.GetRow(arg) : Grid.GetColumn(arg));
}
}However, you might not know that this locality is just an illusion generated by the C# compiler, or more precisely by it's code generation features. In reality the containing class is extended by automatically generated code elements which represent the lambda (and the environment of it, if necessary). All of these elements are added to assembly's meta-data (so that they do consume memory if assembly is loaded...) For your example the compiler would add a new anonymous internal class which represents the closure of the lambda environment. The generated code would look something like this (assuming your class was named
YourClass
and the compiler decided to choose some unique namesXX
andxx
):class YourClass {
\[CompilerGenerated\] private sealed class <>XX : public System.Object { public bool isVertical; public <>XX() {} int <PrintElements>\_xx(int arg) { return IsVetical ? Grid.GetRow(arg) : Grid.GetRow(arg); } } void PrintElements(Grid grid, bool isVertical) { // compiler generated -> class <>XX xx1 = new <>XX(); xx1.IsVertical = isVertical; System.Function<bool, int> xx2 = null; // <- compiler generated foreach (FrameworkElement element in grid.Children) { // compiler generated -> if (xx2 != null) { xx2 = new System.Function<bool, int>(xx1.<PrintElements>\_xx); } Console.WriteLine(xx2); //<-compiler generated } }
}
The compiler possesses a lot of intelligence on deciding what code is going to be generated, in your example a local
isValid
identifier is required so it would generate the local closure class. If no closures are required, it just adds methods (or static methods) to the containing class depending on whether you are using class instance members or not. Interesting, isn't it? Cheers, Paul -
It kinda reminded me of local classes in C++, where you could create a class within a method (with certain restrictions). I always wondered how could they be used, until I read Alexandrescu's Modern C++ Design, where he pointed a particular use: create a class that implements certain interface, so you could have a factory-like method...
Well, this is not allowed in C#, you cannot define classes (or structs) at method scope. However, it'd interesting to know, how the compiler translates the c++0x lambdas. The appropriate definitions in the current standard draft occupy 5 1/2 pages and, as usual, are not clear after first reading... The example from the orginal post would look like this (assuming some hypotetical framework grid_t which defines static methods get_row and get_col and delivers a sequence of children):
void PrintElements(const grid_t& grid, bool isVertical) {
std::transform(grid.children().cbegin(), grid.children().cend(),
std::output_iterator<int>(std::cout), [isVertical](int arg) -> int {
isVertical ? grid_t::get_row(arg) : grid_t::get_col(arg);
});
}Cheers, Paul Edit: As far as I understand what the standard says, the result might look like below (it'd be interesting to see how the code really translates with more complex closures taking environment variables by reference etc...):
void PrintElements(const grid_t& grid, bool isVertical) {
struct XX {
bool xx_IsVertical;
int operator(int arg) {
xx_IsVertical ? grid_t::get_row(arg) : grid_t::get_col(arg);
}XX(bool \_xx) : xx\_IsVertical(\_xx) {}; }; std::transform(grid.children().cbegin(), grid.children().cend(), std::output\_iterator<int>(std::cout), XX(isVertical));
}
modified on Sunday, November 28, 2010 7:25 AM
-
I just discovered how powerful concept is to have a method local to another method. For instance let's assume you have a function that lists the position of elements within a grid. For the sake of simplicity imagine a grid can only have either rows or columns (but not both). Here is what you can do: void PrintElements(Grid grid, bool isVertical) { Func getElementPosition = arg=> isVertical ? Grid.GetRow(arg) : Grid.GetColumn(arg); foreach (FrameworkElement element in grid.Children) { Console.WriteLine(getElementPosition(element)); } } Hence a local func is only visible within PrintElements and can be used in numerous occasions !
Ashish Kaila
-
I just discovered how powerful concept is to have a method local to another method. For instance let's assume you have a function that lists the position of elements within a grid. For the sake of simplicity imagine a grid can only have either rows or columns (but not both). Here is what you can do: void PrintElements(Grid grid, bool isVertical) { Func getElementPosition = arg=> isVertical ? Grid.GetRow(arg) : Grid.GetColumn(arg); foreach (FrameworkElement element in grid.Children) { Console.WriteLine(getElementPosition(element)); } } Hence a local func is only visible within PrintElements and can be used in numerous occasions !
Ashish Kaila
void SortUI(unsigned int* array,const unsigned int count) { typedef struct{ static int cmp(const void *a, const void *b){ return *(int*)a-*(int*)b; } }_; qsort(array,count,sizeof(unsigned int),_::cmp); } void SortSTR(TCHAR** array,const unsigned int count) { typedef struct{ static int cmp(const void *a, const void *b){ return _tcscmp(*(TCHAR**)a,*(TCHAR**)b); } }_; qsort(array,count,sizeof(TCHAR*),_::cmp); } void SortDF(double* array,const unsigned int count) { typedef struct{ static int cmp(const void *a, const void *b){ return *(double*)a<*(double*)b?-1:(*(double*)a>*(double*)b?+1:0); } }_; qsort(array,count,sizeof(double),_::cmp); }
-
void SortUI(unsigned int* array,const unsigned int count) { typedef struct{ static int cmp(const void *a, const void *b){ return *(int*)a-*(int*)b; } }_; qsort(array,count,sizeof(unsigned int),_::cmp); } void SortSTR(TCHAR** array,const unsigned int count) { typedef struct{ static int cmp(const void *a, const void *b){ return _tcscmp(*(TCHAR**)a,*(TCHAR**)b); } }_; qsort(array,count,sizeof(TCHAR*),_::cmp); } void SortDF(double* array,const unsigned int count) { typedef struct{ static int cmp(const void *a, const void *b){ return *(double*)a<*(double*)b?-1:(*(double*)a>*(double*)b?+1:0); } }_; qsort(array,count,sizeof(double),_::cmp); }
Well, exactly this is the reason, why C# was invented... :)