Please help me understand anonymous delegates? - c#

I've downloaded the VCSharpSample pack from Microsoft and started reading on Anonymous Delegates. I can more or less understand what the code is doing, but I don't understand the reason behind it. Maybe if you gave me some examples where it would result in cleaner code and easier maintainability then I could wrap my head around it. :)
Can you help?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication2
{
delegate decimal CalculateBonus(decimal sales);
class Player
{
public string Name;
public decimal Score;
public decimal Bonus;
public CalculateBonus calculation_algorithm;
}
class Program
{
static decimal calculateStandardBonus(decimal sales)
{
return sales / 10;
}
static void Main(string[] args)
{
decimal multiplier = 2;
CalculateBonus standard_bonus = new CalculateBonus(calculateStandardBonus);
CalculateBonus enhanced_bonus = delegate(decimal sales) { return multiplier * sales / 10; };
Player[] players = new Player[5];
for (int i = 0; i < 5; i++)
{
players[i] = new Player();
}
players[0].Name = "Sergio";
players[0].Score = 240;
players[0].calculation_algorithm = standard_bonus;
players[1].Name = "Sergio";
players[1].Score = 240;
players[1].calculation_algorithm = enhanced_bonus;
players[2].Name = "Caro";
players[2].Score = 89;
players[2].calculation_algorithm = standard_bonus;
players[3].Name = "Andy";
players[3].Score = 38;
players[3].calculation_algorithm = enhanced_bonus;
players[4].Name = "Hugo";
players[4].Score = 600;
players[4].calculation_algorithm = enhanced_bonus;
foreach (Player player in players)
{
PerformCalculationBonus(player);
}
foreach (Player player in players)
{
DisplayPersonalDetails(player);
}
Console.ReadLine();
}
public static void PerformCalculationBonus(Player player)
{
player.Bonus = player.calculation_algorithm(player.Score);
}
public static void DisplayPersonalDetails(Player player)
{
Console.WriteLine(player.Name);
Console.WriteLine(player.Score);
Console.WriteLine(player.Bonus);
Console.WriteLine("---------------");
}
}
}

Anonymous delegates are designed to help you make code more readable by being able to define the behavior of a simple delegate inline in another method. This means that if you're dealing with something that requires a delegate (an event handler, for example), you can define the behavior right in the code rather than creating a dedicated function for it.
In addition, they're the precursor for lambda expressions. Things like LINQ to Objects (any of the methods that operate on IEnumerable<T>) use delegates to perform queries on objects. For example, if you have a collection of strings and you want a query that finds all of them that are five characters long, you can do that with a lambda:
List<string> strings = ...
var query = strings.Where(s => s.Length == 5);
Or you could do it with an anonymous delegate:
var query = strings.Where(delegate(string s) { return s.Length == 5; });
If you didn't have these, your code would look something like this:
var query = strings.Where(IsFiveCharacters);
...
private bool IsFiveCharacters(string input)
{
return input.Length == 5;
}
It's important to realize, though, that lambdas and anonymous delegates are just compiler features. When your code is compiled, it does actually create regular functions like in the last example, but they're hidden and named using characters that are illegal in the language being used. There's a lot of logic that goes around them when doing things like closures (where you access a variable that exists outside of the lambda/anonymous delegate declaration), as well.

The benefit is that you don't have to look somewhere else for the code to do a one-time lookup/change/calculation/whatever. It's a bit annoying to have to add a function (or a whole other class for a function!) you'll only ever use in one place, and then you have to look back later and see what that bit of code was and why it's needed and whether it still is.
With an anonymous delegate, the code is right there in the code that uses it.

Related

C# List is adding incorrect members

I am trying to add a few different members to a list, but when the list is added to it contains copies of only the last member added:
private PotentialSolution tryFirstTrack(PotentialSolution ps, List<PotentialSolution> possibleTracks)
{
for (Track trytrack = Track.Empty + 1; trytrack < Track.MaxVal; trytrack++)
{
if (validMove(ps.nextSide, trytrack))
{
ps.SetCell(trytrack);
possibleTracks.Add(ps);
}
}
return tryNextTrack(ps, possibleTracks);
}
The PotentialSolution class looks like this:
public class PotentialSolution
{
public Track[,] board;
public Side nextSide;
public int h;
public int w;
static int cellsPerSide;
static bool testing;
static int minTracks;
.....
public void SetCell(Track t)
{
board[h, w] = t;
}
}
So we are trying to make several copies of the board which only differ by which 'track' is placed in the current cell.
If I have a breakpoint at possibleTracks.Add(ps) then I can see by inspecting ps that the required cell contents is changing each time, as required.
But when the code reaches the next line (or the return statement), the cell content is the same in each member of the list (it's the last one that was added).
What I am doing wrong here? I have tried using an ArrayList and also a basic array instead, but get the same result. It's acting as though the board member is decared as static, but it's not.
[edit]
In response to those who suggested making copies of ps, you are correct and I had tried this before - but only tried single-stepping after the change and didn't run the full program (this method is used hundreds of times). When running the full program, making copies of ps certainly makes a difference to the result (although it's still not correct). The problem now, and why I didn't stick with using the copies, is that an added test still shows the list to contain the same versions of ps, even though the debugger has shown 2 or 3 different tracks being deployed:
private PotentialSolution tryFirstTrack(PotentialSolution ps, List<PotentialSolution> possibleTracks)
{
for (Track trytrack = Track.Empty + 1; trytrack < Track.MaxVal; trytrack++)
{
if (validMove(ps.nextSide, trytrack))
{
PotentialSolution newps = new PotentialSolution(ps);
newps.SetCell(trytrack);
possibleTracks.Add(newps);
}
}
// temporary test, can be removed
if (possibleTracks.Count >= 2)
{
PotentialSolution ps1 = new PotentialSolution(possibleTracks.First());
PotentialSolution ps2 = new PotentialSolution(possibleTracks.Last());
if (ps1.GetCell() != ps2.GetCell())
{
// should always get here but never does
int foo = 1;
}
}
return tryNextTrack(ps, possibleTracks);
}
By the way, Track and nextSide are just enum integers, they will be 0-6, and the list will contain 0,1,2,or 3 members, never more.
You are adding references to the same object: ps in possibleTracks.Add(ps)
You could add a constructor to PotentialSolution duplicating the class:
public class PotentialSolution
{
public Track[,] board;
public Side nextSide;
public int h;
public int w;
static int cellsPerSide;
static bool testing;
static int minTracks;
//.....
public PotentialSolution()
{
}
public PotentialSolution(PotentialSolution ps)
{
board = ps.board;
nextSide = ps.nextSide;
h = ps.h;
w = ps.w;
}
//.....
Then use:
private PotentialSolution tryFirstTrack(PotentialSolution ps, List<PotentialSolution> possibleTracks)
{
for (Track trytrack = Track.Empty + 1; trytrack < Track.MaxVal; trytrack++)
{
if (validMove(ps.nextSide, trytrack))
{
ps.SetCell(trytrack);
possibleTracks.Add(new PotentialSolution(ps)); // duplicate object
}
}
return tryNextTrack(ps, possibleTracks);
}
This creates a new instance of the class each time it is added to the list.
Consider giving the PotentialSolution type value semantics by making it a struct and implementing a Clone method, or a constructor that takes another PotentialSolution as an argument. Also, to clone a 2D array of value types, call Object.Clone() and cast the result to T[,].
When making a copy of your PotentialSolution, you'll need to make sure your clone your board array, because, in your case, each PotentialSolution keeps its own representation of the state of the board.
I feel like the critical part you're missing is how to shallow clone a 2D array, which in general, is:
T[,] copy = (T[,])original.Clone();
WARNING: Clone creates a shallow copy of the array. For value-types this copies the values of each element, so for your int-like "Track" type it does what you want, but for other readers who may be using reference-types (like classes) it does not clone each object referred to by each element of the array. The elements of the new array are just object references, and will still refer to the same objects referred to by the elements of the original array. See the documentation.
Full example below that changes the middle cell of a 3x3 board from A to B.
using System;
using System.Linq;
public enum Track { A, B, C }
public enum Side { X, Y, Z }
public struct PotentialSolution
{
public Track[,] board;
public Side nextSide;
public int h;
public int w;
public void SetCell(Track t)
{
board[h, w] = t;
}
public PotentialSolution(Track[,] board, Side nextSide, int h, int w)
{
this.board = (Track[,])board.Clone();
this.nextSide = nextSide;
this.h = h;
this.w = w;
}
public PotentialSolution Clone()
{
return new PotentialSolution(board, nextSide, h, w);
}
// This `ToString` is provided for illustration only
public override string ToString()
{
var range0 = board.GetLength(0);
var range1 = board.GetLength(1);
var b = board;
return string.Join(",",
Enumerable.Range(0, range0)
.Select(x => Enumerable.Range(0, range1)
.Select(y => b[x, y]))
.Select(z => "[" + string.Join(",", z) + "]"));
}
}
class Program
{
static void Main(string[] args)
{
Track[,] someBoard = new Track[3, 3];
PotentialSolution ps1 = new PotentialSolution(someBoard, Side.X, 1, 1);
ps1.SetCell(Track.A);
PotentialSolution ps2 = ps1.Clone();
ps2.SetCell(Track.B);
Console.WriteLine(ps1);
Console.WriteLine(ps2);
}
}
I'm filling in the blanks liberally, so please excuse any assumptions I have made that differ from your actual situation, because I have done so only to make this example self-contained. My ToString implementation and its usage of System.Linq is not necessary; it's purely for the purposes of displaying the 2D array in my example.
You always call SetCell on the same ps object you received as a parameter then add the same instance to the possibleTracks list. The result is: possibleTrack contains ps n times and because it is the same instance you used in each cycle it will have the last change you applied via SetCell call.
Not sure what you wanted to achieve but it looks you need a modified copy of ps in each cycle for adding to possibleTrack list. Making PotentialSolution a struct instead of class could be enough? Structs are copied in such a way but may hit your performance if PotentialSolution is big.
The board member will still generate the same problem, because despite ps will be copied but the board inside it will contain same Track references. The trick can be applied to Track too, but the performance issues may raise more.
Just implement a Clone on PotentialSolution to have fully detached instances of it, then call ````SetCell``` on cloned instance and add that instance to the list.

Functionally pure dice rolls in C#

I am writing a dice-based game in C#. I want all of my game-logic to be pure, so I have devised a dice-roll generator like this:
public static IEnumerable<int> CreateDiceStream(int seed)
{
var random = new Random(seed);
while (true)
{
yield return 1 + random.Next(5);
}
}
Now I can use this in my game logic:
var playerRolls = players.Zip(diceRolls, (player, roll) => Tuple.Create(player, roll));
The problem is that the next time I take from diceRolls I want to skip the rolls that I have already taken:
var secondPlayerRolls = players.Zip(
diceRolls.Skip(playerRolls.Count()),
(player, roll) => Tuple.Create(player, roll));
This is already quite ugly and error prone. It doesn't scale well as the code becomes more complex.
It also means that I have to be careful when using a dice roll sequence between functions:
var x = DoSomeGameLogic(diceRolls);
var nextRoll = diceRolls.Skip(x.NumberOfDiceRollsUsed).First();
Is there a good design pattern that I should be using here?
Note that it is important that my functions remain pure due to syncronisation and play-back requirements.
This question is not about correctly initializing System.Random. Please read what I have written, and leave a comment if it is unclear.
That's a very nice puzzle.
Since manipulating diceRolls's state is out of the question (otherwise, we'd have those sync and replaying issues you mentioned), we need an operation which returns both (a) the values to be consumed and (b) a new diceRolls enumerable which starts after the consumed items.
My suggestion would be to use the return value for (a) and an out parameter for (b):
static IEnumerable<int> Consume(this IEnumerable<int> rolls, int count, out IEnumerable<int> remainder)
{
remainder = rolls.Skip(count);
return rolls.Take(count);
}
Usage:
var firstRolls = diceRolls.Consume(players.Count(), out diceRolls);
var secondRolls = diceRolls.Consume(players.Count(), out diceRolls);
DoSomeGameLogic would use Consume internally and return the remaining rolls. Thus, it would need to be called as follows:
var x = DoSomeGameLogic(diceRolls, out diceRolls);
// or
var x = DoSomeGameLogic(ref diceRolls);
// or
x = DoSomeGameLogic(diceRolls);
diceRolls = x.RemainingDiceRolls;
The "classic" way to implement pure random generators is to use a specialized form of a state monad (more explanation here), which wraps the carrying around of the current state of the generator. So, instead of implementing (note that my C# is quite rusty, so please consider this as pseudocode):
Int Next() {
nextState, nextValue = NextRandom(globalState);
globalState = nextState;
return nextValue;
}
you define something like this:
class Random<T> {
private Func<Int, Tuple<Int, T>> transition;
private Tuple<Int, Int> NextRandom(Int state) { ... whatever, see below ... }
public static Random<A> Unit<A>(A a) {
return new Random<A>(s => Tuple(s, a));
}
public static Random<Int> GetRandom() {
return new Random<Int>(s => nextRandom(s));
}
public Random<U> SelectMany(Func<T, Random<U>> f) {
return new Random(s => {
nextS, a = this.transition(s);
return f(a).transition(nextS);
}
}
public T Run(Int seed) {
return this.transition(seed);
}
}
Which should be usable with LINQ, if I did everything right:
// player1 = bla, player2 = blub, ...
Random<Tuple<Player, Int>> playerOneRoll = from roll in GetRandom()
select Tuple(player1, roll);
Random<Tuple<Player, Int>> playerTwoRoll = from roll in GetRandom()
select Tuple(player2, roll);
Random<List<Tuple<Player, Int>>> randomRolls = from t1 in playerOneRoll
from t2 in playerTwoRoll
select List(t1, t2);
var actualRolls = randomRolls.Run(234324);
etc., possibly using some combinators. The trick here is to represent the whole "random action" parametrized by the current input state; but this is also the problem, since you'd need a good implementation of NextRandom.
It would be nice if you could just reuse the internals of the .NET Random implementation, but as it seems, you cannot access its internal state. However, I'm sure there are enough sufficiently good PRNG state functions around on the internet (this one looks good; you might have to change the state type).
Another disadvantage of monads is that once you start working in them (ie, construct things in Random), you need to "carry that though" the whole control flow, up to the top level, at which you should call Run once and for all. This is something one needs to get use to, and is more tedious in C# than functional languages optimized for such things.

Update PointF Value Using Extension Method in C# [duplicate]

I want to be able to write extension methods so that I can say:
lines.ForceSpaceGroupsToBeTabs();
instead of:
lines = lines.ForceSpaceGroupsToBeTabs();
However, the following code currently outputs:
....one
........two
instead of:
Tone
TTtwo
What do I have to change in the following code to make it output:
Tone
TTtwo
(note that for visibility, . = space, T = \t):
using System;
using System.Collections.Generic;
namespace TestExtended82343
{
class Program
{
static void Main(string[] args)
{
List<string> lines = new List<string>();
lines.Add("....one");
lines.Add("........two");
lines.ForceSpaceGroupsToBeTabs();
lines.ForEach(l => Console.WriteLine(l));
Console.ReadLine();
}
}
public static class Helpers
{
public static void ForceSpaceGroupsToBeTabs(this List<string> originalLines)
{
string spaceGroup = new String('.', 4);
List<string> lines = new List<string>();
foreach (var originalLine in originalLines)
{
lines.Add(originalLine.Replace(spaceGroup, "T"));
}
originalLines = lines;
}
}
}
You have to modify the contents of the List<string> passed to the extension method, not the variable that holds the reference to the list:
public static void ForceSpaceGroupsToBeTabs(this List<string> lines)
{
string spaceGroup = new String('.', 4);
for (int i = 0; i < lines.Count; i++)
{
lines[i] = lines[i].Replace(spaceGroup, "T");
}
}
You'd have to change the contents of the original list - just reassigning the parameter to have a different value isn't going to do it. Something like this:
public static void ForceSpaceGroupsToBeTabs(this List<string> lines)
{
string spaceGroup = new String('.', 4);
for (int i = 0; i < lines.Count; i++)
{
lines[i] = lines[i].Replace(spaceGroup, "T");
}
}
It's worth noting that this has nothing to do with extension methods. Imagine you'd just called:
Helpers.ForceSpaceGroupsToBeTabs(lines);
... because that's what the code is effectively translated into. There's nothing special about the fact that it's an extension method; if you change the code so that the "normal" static method will work, then it'll work as an extension method too. As noted in the comments, one thing you can't do with an extension method is make the first parameter a ref parameter.
(EDIT: I realise this is the exact same code that dtb posted, although we arrived there independently. I'm keeping this answer anyway, as it's got more than code.)
If it's a reference type, you'd have to change it's contents. If it's a value type you're passing in, you're out of luck. The very existence of extension methods is put into place to support functional paradigms in C#, and those functional paradigms, by their very essence, tend towards immutability of types, hence the inability to change the value off of which the extension method is called.
In other words, while you could do it, it may not be in keeping with the "spirit" of functional programming.

as3 to c# porting a function within function?

I'm trying to port some AS3 code to C#(.NET) the majority of it has been done (90%) however I have run into a few problems in terms of Functions in Functions and functions being defined as Functions (I hope i'm understanding it correctly). I have done a lot of searching and the main thing that comes up is delegates and lambda's however trying to implement them is proving difficult for me to do. Seen as quiet a few sections are the same in layout ill just post a generic example of the AS3 code and hopefully can then apply any solution to the rest.
Here is the AS3 code:
static public function makeRadial(seed:int):Function {
var islandRandom:PM_PRNG = new PM_PRNG();
islandRandom.seed = seed;
var bumps:int = islandRandom.nextIntRange(1, 6);
var startAngle:Number = islandRandom.nextDoubleRange(0, 2*Math.PI);
var dipAngle:Number = islandRandom.nextDoubleRange(0, 2*Math.PI);
var dipWidth:Number = islandRandom.nextDoubleRange(0.2, 0.7);
function inside(q:Point):Boolean {
var angle:Number = Math.atan2(q.y, q.x);
var length:Number = 0.5 * (Math.max(Math.abs(q.x), Math.abs(q.y)) + q.length);
var r1:Number = 0.5 + 0.40*Math.sin(startAngle + bumps*angle + Math.cos((bumps+3)*angle));
var r2:Number = 0.7 - 0.20*Math.sin(startAngle + bumps*angle - Math.sin((bumps+2)*angle));
if (Math.abs(angle - dipAngle) < dipWidth
|| Math.abs(angle - dipAngle + 2*Math.PI) < dipWidth
|| Math.abs(angle - dipAngle - 2*Math.PI) < dipWidth) {
r1 = r2 = 0.2;
}
return (length < r1 || (length > r1*ISLAND_FACTOR && length < r2));
}
return inside;
}
In the AS3 code I don't understand the reasoning behind the ":Function" in the main function "static public function makeShape(seed:int):Function". I did search about it but was unable to find an example or explanation perhaps i'm not typing the correct meaning for it.
If anyone could help me with this problem by giving an example or pointing me closer in the direction I need to go I would be very grateful.
Thanks for your time.
The most direct translation would be to return a delegate. In this case, the generic Func<Point, bool> delegate would be sufficient. It's pretty easy to create these in C# using lambda expressions:
static public Func<Point, bool> makeShape(int seed) {
// initialization here
Func<Point, bool> inside = (Point q) => {
// some math here
return (myCondition);
}
return inside;
}
Although you can define your own delegate type if you prefer:
public delegate bool ShapeTester(Point point);
static public ShapeTester makeShape(int seed) {
// initialization here
ShapeTester inside = (Point q) => {
// some math here
return (myCondition);
}
return inside;
}
Another approach, but one which would require quite a bit more effort in refactoring, would be to encapsulate all the logic of what makes up 'shape' into a distinct type, for example:
public class Shape
{
public Shape(int seed)
{
// initialization here
}
public bool Test(Point q)
{
// some math here
return (myCondition);
}
}
And then return an instance of this type from your makeShape method:
static public Shape makeShape(int seed) {
return new Shape(seed);
}
And elsewhere you'd need to call the test method on the resulting object. Depending the specific you're developing, you may make more since if Shape is actually be an interface (IShape) or a struct. But in any case, using this approach, traditional OOP design principles (inheritance, polymorphism, etc.) should be followed.

Reading values out from an ArrayList in an independent function

I am having troubling reading my values out of an ArrayList. The compiler goes into the ReadOutFromArray function, but skips the Console.WriteLine(st)? Can anyone tell me where I went wrong. Been on it for a couple of hours chasing my tail. Thanks.
using System;
using System.IO;
using System.Collections.Generic;
using System.Collections;
using System.Text;
namespace BoolEx
{
class Program
{
static void Decision(ArrayList decis)
{
bool ans = true;
decis = new ArrayList();
//ArrayList aList = new ArrayList();
while (ans)
{
Console.WriteLine("1=True 0=False");
int x = Int32.Parse(Console.ReadLine());
if (x == 1)
{
ans = true;
}
else
{
ans = false;
}
if (ans == true)
{
ReadInArray(decis);
}
else
{
ReadOutArray(decis);
}
}
}
static void ReadInArray(ArrayList f)
{
f= new ArrayList();
Console.WriteLine("Enter in a name");
f.Add(Console.ReadLine());
}
static void ReadOutArray(ArrayList d)
{
d = new ArrayList();
ReadInArray(d);
foreach (string st in d)
{
Console.WriteLine(st);
}
}
static void Main(string[] args)
{
ArrayList g = new ArrayList();
Decision(g);
}
}
}
The problem is your ReadInArray method:
static void ReadInArray(ArrayList f)
{
f= new ArrayList();
Console.WriteLine("Enter in a name");
f.Add(Console.ReadLine());
}
In the first line of the method, you're basically saying, "I don't care what ArrayList reference was passed in - I'm going to overwrite the local variable f with a reference to a new ArrayList."
I suspect you meant something like this:
static void ReadInArray(ArrayList f)
{
f.Clear();
Console.WriteLine("Enter in a name");
f.Add(Console.ReadLine());
}
If you don't understand why that changes things, see my parameter passing article.
Other things you should consider:
If you're only going to read a single line, why not use something like this:
static string ReadNameFromUser()
{
Console.WriteLine("Enter in a name");
return Console.ReadLine();
}
The same sort of thing occurs elsewhere. Don't try to use collections for all your input and output. Returning a value is much clearer than populating a list which is passed into the method.
Given that you can obviously refer to generic collections (given your using directives) you should really consider using List<string> instead of ArrayList
Code like this:
if (x == 1)
{
ans = true;
}
else
{
ans = false;
}
... would be better written as
ans = (x == 1);
(The brackets are optional, but help readability.)
Code like this:
if (ans == true)
is better written as:
if (ans)
Although I do agree with everything Skeet has mentioned, it appears the poster is trying to understand some things and I think
Jon might have missed that.
First if all you want to do is fill a list and print it try this:
static void (main)
{
ArrayList l = new ArrayList();
FillMyList(l);
DisplayMyList(l);
}
public static void FillMyList(ArrayList temp)
{
for(int i = 0; i < 10; i++)
temp.Add(i);
}
public static void DisplayMyList(ArrayList temp)
{
foreach(int i in temp)
Console.WriteLine(i);
}
Second thing is take what Jon Skeet has mentioned and definately understand some things. Booleans are just true / false (unless you introduce the nullable types) but for now keep it simple.
ArrayList is really old school, it kind of suffers like the HashTable in that you can easily run into trouble adding different data types into the object (read up on boxing of data types and unboxing).
Finally, you should really replace anything with this System.Collection.ArrayList to System.Collections.Generic.List.
The list class is a generic class and is made available so that you don't have to deal with the issues that you could encounter when dealing with array lists or hash tables.
Edit
I noticed you were asking users to add items to the list. You can do this using a do while loop instead of the for loop I posted, something to this effect (note i have not tested any of this):
public static void FillMyList(ArrayList temp)
{
char c='y';
do {
Console.WriteLine("Enter a value");
int x = Int32.Parse(Console.ReadLine());
temp.Add(x);
Console.WriteLine("Continue adding numbers to list, if so type y");
char c = Console.ReadLine();
}while(c=='y' || c=='Y');
}
Again I am just giving you examples here, you will have to handle user input in case someone doesn't enter the correct information, exceptions, etc.

Categories

Resources