I'll add a few comments to the useful answers here by George Jonsson and Garth Lancaster; I'll focus on the use of
delegates. By the way, lots of smart people beginning C# (without a background in other languages where the equivalent of 'delegates exists) have trouble "getting" what delegates are about.
A
delegate can be thought of as a
template for a unit of executable code.
So, if we define:
private delegate void KeyCommand();
In effect, we've "declared" a new 'Type, a prototype, a template that we can make instances from into which we can insert any method into ... as long as the method has the same
signature as the delegate ... which means that the types of any return value and of parameters must be identical.
In this case, the signature is of a method which takes no parameters, and returns nothing (void).
Some find it helpful to recite the following when thinking of delegates: "The Delegate is a 'Type, to use it, we must have instances" :)
Since all your cursor movement methods have a signature which matches 'KeyCommand, any of them can be used as the "content" of an instance of the delegate.
So, we could write:
KeyCommand up = Up;
, and then anytime we executed up(); we'd be calling your method, 'Up.
The power of using delegates is when we wish to use executable code at run-time and we need the flexibility of using different executable code depending on ... whatever. So, we can define any number of delegate instances, bind them to method code that matches the signature of the delegate, and use them flexibly.
We can create a generic Dictionary that pairs ConsoleKey values (ConsoleKeyInfo.Key) with executable code by using the delegate
using System.Collections.Generic;
private delegate void KeyCommand();
Dictionary<ConsoleKey, KeyCommand> KeysToCommands = new Dictionary<ConsoleKey, KeyCommand>
{
{ConsoleKey.RightArrow, Right},
{ConsoleKey.LeftArrow, Left},
{ConsoleKey.DownArrow, Down},
{ConsoleKey.UpArrow, Up}
};
Using this Dictionary, we can execute any method by using the ConsoleKey value to access the executable code:
KeysToCommands[ConsoleKey.Up](); // executes 'Up
Note: when you use Console.ReadKey(true) the return value is an instance of the ConsoleKeyInfo object (struct). You get the ConsoleKey value from the ConsoleKeyInfo.Key property.
Beginning with C#3.0, anonymous delegates which can be written using Lambda notation were added to the C# language/compiler; so now, you can write this:
Dictionary<ConsoleKey, KeyCommand> KeysToCommands = new Dictionary<ConsoleKey, KeyCommand>
{
{ConsoleKey.RightArrow, () => { x++; }},
{ConsoleKey.LeftArrow, () => { x--; }},
{ConsoleKey.DownArrow, () => { y++; }},
{ConsoleKey.UpArrow, () => { y--; }},
};
Understanding delegates and their flexibility is a powerful tool that you will find has many uses; delegates are the basis for C# multi-cast Events:
"Events and delegates are tightly coupled concepts because flexible event handling requires that the response to the event be dispatched to the appropriate event handler. An event handler is typically implemented in C# via a delegate."
Jessie Liberty "Learning C# 3.0" as quoted in Microsoft's re-publication of his Chapter 17 [
^]