|
thanks Griff thats something new learnt today!
Lobster Thermidor aux crevettes with a Mornay sauce, served in a Provençale manner with shallots and aubergines, garnished with truffle pate, brandy and a fried egg on top and Spam - Monty Python Spam Sketch
|
|
|
|
|
Thank you for quick reply.
I am getting what you are saying but what is confusing me is that (GameStarted, GameOver and PieceUpdated) are not declared as Event but if you see the class they are themselves declared as EvenHandlers, that is where I have bit of confusion.
Can you please help me understanding this concept, I migght be mssing on something here.
|
|
|
|
|
events are just a specialized version of a delegate. A delegate (EventHandler here) can be used without the event keyword, but you do not get the protection that the event keyword gives.
|
|
|
|
|
Sorry - I missed that the event keyword was missing - blame the lack of coffee!
In this case, all that is happening is that EventHandler is being used as the prototype for the method signature.
Or, in plainer English:
The GameStarted variable is declared as being an EventHandler - which is a delegate returning a void, and accepting an object and an EventArgs as parameters. The code
this.game.GameStarted += delegate
{
this.ResetWinTransition.Begin();
this.StatusPanel.Visibility = Visibility.Visible;
this.TapToContinueTextBlock.Opacity = 0;
this.TotalMovesTextBlock.Text = this.game.TotalMoves.ToString();
};
adds an anonymous method to the execution list, so that when later the code:
GameStarted(null, null); is executed, the anonymous method is called - as are any others that have been added.
Basically, whoever wrote the code is too lazy to declare his own method prototype which has no parameters, so he uses one which happens to exist already. Really he should have created his own delegate type to avoid any confusion:
public delegate void GameMethod();
public GameMethod GameStarted; He could then have executed the chained list of methods by calling:
GameStarted(); Instead of supplying unused parameters.
Ideological Purity is no substitute for being able to stick your thumb down a pipe to stop the water
|
|
|
|
|
Thank you for the clarification and now able to understand better.
Below is how all three are used.
if (this.GameStarted != null)
{
this.GameStarted(this, null);
}
if (this.GameOver != null)
{
this.GameOver(this, new GameOverEventArgs { TotalMoves = this.totalMoves });
}
if (this.PieceUpdated != null)
{
this.PieceUpdated(this, new PieceUpdatedEventArgs {PieceId = pieceId, NewPosition = newPosition});
}
Thank you all for your replies and helping me understand the code.
|
|
|
|
|
Okay, you have potential race conditions in your code here. If your event handlers can be triggered from multi threaded code, it's possible that the event handler is dereferenced between your null check and the time it actually fires. To that end, it's generally a good idea to copy your event handler to a local variable, test that for null and then invoke on that. Here's an example:
var handler = GameStarted;
if (handler != null)
{
handler(this, null);
}
|
|
|
|
|
In .Net 1, you had to explicitly instantiate a delegate from a method:
EventHandler GameStarted = new EventHandler(GameStartedMethod);
void GameStartedMethod(object sender, EventArgs e) { ... }
Although clear, this was a bit messy and wasted a lot of time, so in .Net 2 and up you are allowed to implicitly cast the method, even though that appears to be assigning a method to a variable/property:
EventHandler GameStarted = GameStartedMethod;
void GameStartedMethod(object sender, EventArgs e) { ... }
You are also allowed to create an anonymous, inline method to assign to the delegate, using the delegate keyword:
EventHandler GameStarted = delegate(object sender, EventArgs e) { ... }
The delegate keyword approach allows you to omit the parameter list, if you don't need to refer to the parameters, which you often don't with event handlers:
EventHandler GameStarted = delegate { ... }
Finally, in .Net 3 and up, you can use lambda functions to create anonymous functions that can be used as a delegate:
EventHandler GameStarted = (sender, e) => { ... }
All of these are equivalent, and result in a delegate that points at a method. In the first two cases, that method has a name and can be called normally as well; in the others, it is anonymous and only exists in the context of the delegate.
When calling a delegate, normal method syntax is used.
|
|
|
|
|
A couple of points. The first being that the anonymous function creates a closure, allowing you to access local scope variables. The second point relates to the lifetime of the event handler - anonymous functions can be notoriously difficult to unregister.
|
|
|
|
|
That's one of the reasons I don't like 'em!
Ideological Purity is no substitute for being able to stick your thumb down a pipe to stop the water
|
|
|
|
|
Pete O'Hanlon wrote: anonymous functions can be notoriously difficult to unregister
Hi Pete,
I rarely use anonymous functions (I prefer the clarity provided by having a 'proper' method call) but hadn't considered unregistering from an event in that scenario. A good point!
|
|
|
|
|
Pete O'Hanlon wrote: anonymous functions can be notoriously difficult to unregister.
Excellent point !
When I was a coder, we worked on algorithms. Today, we memorize APIs for countless libraries — those libraries have the algorithms - Eric Allman
|
|
|
|
|
I have gone through all the replies but I am not able to convert the code in the simple understandable format.
I am pasting the the two .cs file below, if someone can help putting it in the simple fashion for all the 3 eventhandler delegates.
1) PuzzleGame.cs
using Mosaic;
namespace WindowsPhonePuzzle
{
public class PieceUpdatedEventArgs : EventArgs
{
public int PieceId { get; set; }
public Point NewPosition { get; set; }
}
public class GameOverEventArgs : EventArgs
{
public int TotalMoves { get; set; }
}
public class PuzzleGame
{
public EventHandler GameStarted;
public EventHandler<PieceUpdatedEventArgs> PieceUpdated;
public EventHandler<GameOverEventArgs> GameOver;
if (this.GameStarted != null)
{
this.GameStarted(this, null);
}
}
if (this.GameOver != null)
{
this.GameOver(this, new GameOverEventArgs { TotalMoves = this.totalMoves });
}
}
}
if (this.PieceUpdated != null)
{
this.PieceUpdated(this, new PieceUpdatedEventArgs {PieceId = pieceId, NewPosition = newPosition});
}
}
}
}
2) PuzzlePage.xaml.cs
<pre lang="c#">
using WindowsPhonePuzzle;
namespace Mosaic
{
public partial class PuzzlePage : PhoneApplicationPage
{
public PuzzlePage()
{
InitializeComponent();
SupportedOrientations = SupportedPageOrientation.Portrait | SupportedPageOrientation.Landscape;
this.game = new PuzzleGame(3);
this.game.GameStarted += delegate
{
this.ResetWinTransition.Begin();
this.StatusPanel.Visibility = Visibility.Visible;
this.TapToContinueTextBlock.Opacity = 0;
this.TotalMovesTextBlock.Text = this.game.TotalMoves.ToString();
};
this.game.GameOver += delegate
{
this.WinTransition.Begin();
this.TapToContinueTextBlock.Opacity = 1;
this.StatusPanel.Visibility = Visibility.Visible;
this.TotalMovesTextBlock.Text = this.game.TotalMoves.ToString();
};
this.game.PieceUpdated += delegate(object sender, PieceUpdatedEventArgs args)
{
int pieceSize = ImageSize / this.game.ColsAndRows;
this.AnimatePiece(this.puzzlePieces[args.PieceId], Canvas.LeftProperty, (int)args.NewPosition.X * pieceSize);
this.AnimatePiece(this.puzzlePieces[args.PieceId], Canvas.TopProperty, (int)args.NewPosition.Y * pieceSize);
this.TotalMovesTextBlock.Text = this.game.TotalMoves.ToString();
};
this.InitBoard();
}
modified 12-Jul-12 8:40am.
|
|
|
|
|
Sorry, but no.
Nobody is going to wade through that much code and "tidy it up" for you!
Ideological Purity is no substitute for being able to stick your thumb down a pipe to stop the water
|
|
|
|
|
No Problems at all.
I thought the way quick inputs were provided by all it should be quick to replace 3 calls simple code or just simple pointer for one would be fine.
I just wanted to understand how it will work in simple call then in this twisted fashion.
Thanks to all.
|
|
|
|
|
I have removed all the irrelevant code from modified the post.
Can now someone help in simplyfying it. One is the class file where the event handlers are decalared and other is the actual page file where definition is there <inline> as well call to the inline code is happening from it.
Thanks
|
|
|
|
|
What and where is the problem?
|
|
|
|
|
In puzzlepage.xaml.cs as shown in my modified post, there is code starting with line as shown below.
<pre lang="c#">
this.game.GameStarted += delegate
I want to convert it in the simple form, which I am not able to do.
The code is fine and its working, onlt thing is that to understand the delegate better I want to see how actually its working.
Thanks
|
|
|
|
|
Griff has given you the answer Hope you have got the concept now.
|
|
|
|
|
|
There are only two changes you can really make there: the first is to change from anonymous methods to named methods.
this.game.GameStarted += delegate
{
this.ResetWinTransition.Begin();
this.StatusPanel.Visibility = Visibility.Visible;
this.TapToContinueTextBlock.Opacity = 0;
this.TotalMovesTextBlock.Text = this.game.TotalMoves.ToString();
}; Becomes
this.game.GameStarted += MyGameStarted;
...
private void MyGameStarted(object sender, EventArgs e)
{
this.ResetWinTransition.Begin();
this.StatusPanel.Visibility = Visibility.Visible;
this.TapToContinueTextBlock.Opacity = 0;
this.TotalMovesTextBlock.Text = this.game.TotalMoves.ToString();
}; This is a matter largely of style - as I said I prefer named methods, but have a look at the other comments you got before you make your mind up.
The other change looks trivial, and it adds a little code, but it is something I do with all delegates, be they event handlers or not.
if (this.GameStarted != null)
{
this.GameStarted(this, null);
} Becomes
EventHandler eh = GameStarted;
if (eh != null)
{
eh(this, null);
} The only difference is that I read the value once, and action from that value, while your code reads it twice. If the delegate method is removed from the list between the two instructions, your version will get a null reference, while mine won't. That said, it is very,. very unlikely to ever happen, but I prefer to code for the unlikely events as well as the common ones!
As a side note, you don't need to write this so often - I almost never use it, except where a local variable masks the name of the class level version:
private string name;
public string Name {get { return name; } set { name = value; } }
public MyClass(string name)
{
this.name = name;
} The rest of the time there is no conflict, so the clear resolution of name to a class level variable is unneccessary:
Console.WriteLine(this.name); Is identical to:
Console.WriteLine(name); But the latter needs less typing and is quicker to read.
Ideological Purity is no substitute for being able to stick your thumb down a pipe to stop the water
|
|
|
|
|
Thank you sir. I could change code now to simple format.
Really appreciate your help, it has given me lot of insigt into the Delegate concept today.
"A Day is wasted if you have not learned anything new, and today I have learned a lot."
Thanks
|
|
|
|
|
A good sentiment.
And you are welcome!
Ideological Purity is no substitute for being able to stick your thumb down a pipe to stop the water
|
|
|
|
|
5 to all of the above
|
|
|
|
|
By using += we attach a delegate handler to the appropriate method that needs to be called when the handler is invoked.
In your example, += is used to attach the GameStarted and GameOver handlers to anonymous methods that would be executed when these handlers are invoked.
|
|
|
|
|
please tell me the concept of delegates. I have seen from it from book but didnt get it properly.. what i read is it is a type safe object that can point to another method or multiple method in the application which can be invoked at later time.
|
|
|
|