Can someone help me understand anonymous functions in C#? - c#

I'm currently following a Unity course. In one of the lessons, the lecturer uses an anonymous function that sorts the results by actionValue.
Here's the relevant code:
public EnemyAIAction GetBestEnemyAIAction()
{
List<EnemyAIAction> enemyAIActionList = new List<EnemyAIAction>();
List<GridPosition> validActionGridPositionList = GetValidActionGridPositionList();
foreach(GridPosition gridPosition in validActionGridPositionList)
{
EnemyAIAction enemyAIAction = GetEnemyAIAction(gridPosition);
enemyAIActionList.Add(enemyAIAction);
}
enemyAIActionList.Sort(
(EnemyAIAction a, EnemyAIAction b) => b.actionValue - a.actionValue
);
}
The lecturer doesn't bother explaining why this approach sorts the list by actionValue. I'm having trouble understanding how, exactly, subtracting the inputs from each other sorts the list by that input value.

The Sort method is declared as
public void Sort (Comparison<T> comparison);
Comparison<T> is declared as
public delegate int Comparison<in T>(T x, T y);
According to the documentation, it returns A signed integer that indicates the relative values of x and y, as shown in the following table.
Value
Meaning
Less than 0
x is less than y.
0
x equals y.
Greater than 0
x is greater than y.
I.e., the Sort method expects a delegate. You can think of a delegate as the address of a function. In this specific case the function accepts two items of the list as input parameters. The return value is a negative int when x is less than y, 0 when both items are considered as equal, and a positive int when x is greater than y.
Now you could declare your own method like this to sort in ascending order:
int EnemyAIActionComparison(EnemyAIAction x, EnemyAIAction y)
{
if (x.actionValue > y.actionValue) return +1;
if (x.actionValue < y.actionValue) return -1;
return 0; // both are equal
}
Since it does not matter how large the result is (only the sign matters), you could simply write
int EnemyAIActionComparison(EnemyAIAction x, EnemyAIAction y)
{
return x.actionValue - y.actionValue;
}
Then call the Sort method like this:
enemyAIActionList.Sort(EnemyAIActionComparison);
Note that no braces must follow EnemyAIActionComparison() because we are not calling the method here, we are passing the method itself as a parameter to Sort. Sort then calls this method on many pairs of list items according to a sorting algorithm (e.g., Quick Sort) until the list is sorted.
Now, there is a shortcut in defining this method: you can use a lambda expression. A lambda expression is a very concise syntax for declaring an anonymous method on the fly.
So (x, y) => x.actionValue - y.actionValue is equivalent to the method above. The type of the parameters is inferred from the declaration int Comparison<in T>(T x, T y) and T is given in the declaration of the list. So, you do not need to specify it as in the example you have given. (Note that the names you give to the parameters does not matter. Specifically, they do not need to be the same as in the declaration of Comparison.)
If you want to sort in descending order, just swap the signs, i.e., swap the values in the subtraction.

Related

How can I parse a string that represents a chain of generic methods?

In my app I need to parse a string like this, ".Add(20).Subtract(10).Add(2)" in a generic way into a series of method calls. In code I will supply the user with a value of T, and then expect the user to type an expression of the above format to calculate a new T from the expression. In the above example, I show the user an int and they typed the above string.
I need to aggregate any number of these chained string-representation of method calls into one cache-able property (delegate? Func<T,T>?) so that whenever a new value of T comes along it can be passed through the cached expression.
I initially thought there would be a way to aggregate these like a functional-programming pipeline, the outcome being a Func<T,T> that could represent the pipeline of methods. I'm guaranteed to know typeof(T) beforehand.
I'm hitting issues. Here's where I'm at:
I can regex the string with
\.(?<expName>[A-Z,a-z]+)\((?<expValue>[^)]+)\)
To get these matches:
expName
expValue
"Add"
"20"
"Subtract"
"10"
"Add"
"2"
I was expecting to use a TypeConverter to parse all expValue matches but I realized that given an arbitrary method T Foo(object arg) the arg can be any type to be determined by the specific method. The only guarantee is that a T input should always result in a T output.
We already know what type T is so we can theoretically map typeof(T) to a set of strings representing method names. I tried creating Dictionaries like this:
public static readonly Dictionary<string, Func<double, double, double>> DoubleMethods = new Dictionary<string, Func<double, double, double>>()
{
{"Add",(d,v)=>d+v },
{"Subtract",(d,v)=>d-v },
{"Multiply",(d,v)=>d*v },
{"Divide",(d,v)=>d/v }
};
public static Dictionary<string, Func<T, T, T>> TypeMethods<T>(Type t)
{
if(t.GetType() == typeof(double)) { return DoubleMethods; }
}
This won't compile, as I can't mix generics like this.
How do I create a linking structure that maps strings of predefined method names to a method, and then pass it the arg?
I also see that I will incur a bunch of boxing/unboxing penalties for arguments that happen to be primitive types, as in the example int.Add(int addedVal) method.
I believe I'm delving into parser/lexer territory without much familiarity.
Can you give an example of some code to point me in the right direction?
I'm not sure I see the need for the generics part:
var ops = "Add(20).Subtract(10).Divide(2).Multiply(5)";//25
var res = ops
.Split("().".ToCharArray(), StringSplitOptions.RemoveEmptyEntries)
.Chunk(2)
.Aggregate(0.0,(r,arr)=> r = DoubleMethods[arr[0]](r, double.Parse(arr[1])));
All those inputs parse as double, so let's just break the input string into chunks of 2 after splitting on the punctuation:
Add 20
Subtract 10
Divide 2
Multiply 5
Then run an agg op where we start from 0 (I wanted to start from 20 actually so that is what the add 20 is for)
The agg op looks up the method to call in the dictionary using the first element of the chunk
DoubleMethods[arr[0]]
And calls it passing in the current accumulator value r and the double parsing of the second element of the chunk:
(r, double.Parse(arr[1]))
and store the result into the accumulator for passing into the next op
I commented "do it in decimal" because it doesn't have floating point imprecision, but I used double just because your code did; you could swap to using decimal if you like, main point being that I can't see why you're worried about generics when decimal/double can store values one would encounter in ints too.
//basevalue is the value of the code your applying the change to.
soo... lets pretend the class is called number
Number ect = new Number(startingAmount)
in number we would have startingAmount = this.baseValue
public static T add(T baseValue, T change){
return baseValue+change;
}
public static T subtract(T baseValue, T change){
return baseValue-change;
}
public static T multiply(T baseValue, T change){
return baseValue*change;
}
public static T divide(T baseValue, T change){
return baseValue/change;
}
This should work... At least I hope it does
Here is a video on generics https://www.youtube.com/watch?v=K1iu1kXkVoA&t=1s
Java == c# so everything should be almost exactly the same

What's the correct way to implement operator ++ for value-types?

I'm working on a custom implementation of a Number struct, with very different ways of storing and manipulating numeric values.
The struct is fully immutable - all fields are implemented as readonly
I'm trying to implement the ++ and -- operators, and I've run into a little confusion:
How do you perform the assignment?
Or does the platform handle this automatically, and I just need to return n + 1?
public struct Number
{
// ...
// ... readonly fields and properties ...
// ... other implementations ...
// ...
// Empty placeholder + operator, since the actual method of addition is not important.
public static Number operator +(Number n, int value)
{
// Perform addition and return sum
// The Number struct is immutable, so this technically returns a new Number value.
}
// ERROR here: "ref and out are not valid in this context"
public static Number operator ++(ref Number n)
{
// ref seems to be required,
// otherwise this assignment doesn't affect the original variable?
n = n + 1;
return n;
}
}
EDIT: I think this is not a duplicate of other questions about increment and decrement operators, since this involves value-types which behave differently than classes in this context. I understand similar rules apply regarding ++ and --, but I believe the context of this question is different enough, and nuanced enough, to stand on its own.
The struct is fully immutable - all fields are implemented as readonly
Good!
I'm trying to implement the ++ and -- operators, and I've run into a little confusion: How do you perform the assignment?
You don't. Remember what the ++ operator does. Whether it is prefix or postfix it:
fetches the original value of the operand
computes the value of the successor
stores the successor
produces either the original value or the successor
The only part of that process that the C# compiler does not know how to do for your type is "compute the successor", so that's what your overridden ++ operator should do. Just return the successor; let the compiler deal with figuring out how to make the assignment.
Or does the platform handle this automatically, and I just need to return n + 1?
Yes, do that.
The processing of ++ and -- operators is described in C# language specification, section 7.7.5 Prefix increment and decrement operators:
The run-time processing of a prefix increment or decrement operation of the form ++x or --x consists of the following steps:
• If x is classified as a variable:
  o x is evaluated to produce the variable.
  o The selected operator is invoked with the value of x as its argument.
  o The value returned by the operator is stored in the location given by the evaluation of x.
  o The value returned by the operator becomes the result of the operation.
So a custom overloads of these operators only need to produce an incremented/decremented value. The rest is handled by the compiler.
A Number class is going to have a value of some kind as a property.
public static Number operator ++(Number n)
{
// ref seems to be required,
// otherwise this assignment doesn't affect the original variable?
n.value = n.value + 1;
return n;
}
This should do what you want.
I wrote this using your struc and added the value property.
private static void Main(string[] args)
{
var x = new Number();
x.value = 3;
x++;
Console.WriteLine(x.value);
Console.Read();
}
This properly generates a 4
The statement num++; by itself expands to num = PlusPlusOperator(num);. Since your data type is immutable, just return n+1; and the compiler will handle the rest.

How does sorting a C# List based on a property work?

So, I'm doing an assignment for my C# class and I have a list of objects. These objects have an 'int rand' field which is assigned a random number. I then wanted to re-sort the objects in the list based on this rand field.
I found this article:
http://www.developerfusion.com/code/5513/sorting-and-searching-using-c-lists/
And it helped. I modified this line to fit my code:
people.Sort(delegate(Person p1, Person p2) { return p1.age.CompareTo(p2.age); });
And it does what I want.
What I want to know is: how does it work? That looks very confusing to me.
In fact Sort Method should sort base on some comparison, in your current code you passed comparison as delegate, you can also embed it in class definition to reduce code complexity, In fact it just needed to implement IComparable for your Person class:
public class Person : IComparable
{
public int age { get; set; }
public int CompareTo(object obj)
{
var person = obj as Person;
if (person != null)
{
if (age > person.age)
return 1;
else if (age == person.age)
return 0;
return -1;
}
return 1;
}
}
then simply use sort without delegates.
If you use Lambda notation with it gets a little easier to read IMO:
people.Sort((p1, p2) => p1.age.CompareTo(p2.age));
When you use the sort method you are sorting the list, but the method needs to know what to sort by, and this is where the delegation becomes handy as you can use the sort method to specify any sorting you want. You are looking at person 1 and person 2 and are ordering by age. If you wanted to sort by something else like a Name (If you had a Name property), you would write it as:
people.Sort((p1, p2) => string.Compare(p1.Name, p2.Name));
the list will use the function passed in (the return p1.age.CompareTo(p2.age); part) to compare the different objects in the list. It basically allows you to "teach" the list how you want the items compared.
The list will call your function, passing in 2 instances of the class that should be compared. you return -1 to say the 1st is less than the 2nd, 0 to say they are equal, and 1 to say the 2nd is greater. Your example just passes the call on to the built in comparison (that returns the same -1, 0, 1 pattern) for whatever type the age variable is, most likely an integer.
In order to sort, you need to be able to figure out if one item goes before or after another thing. It makes sense that this "comparator" would be a function or method as it compartmentalizes the knowledge away.
If you look at the documentation for CompareTo you'll notice that it's intended to return -1 (B goes before A), 0, (A and B are equal) or 1 (B goes after A).
The delegate keyword in this instance creates an anonymous function which is used as the comparator, and the body of that function calls CompareTo to compare the age property of the two people involved and return the result.
The result of calling this method on every potential pair of items (or some subset - I'm not sure exactly how Sort is implemented) is then used internally by the Sort method to figure out where to place the resulting item (in front of or behind of p2) in this example.
List.Sort uses Quick sort algo to sort the list. The worst case complexity is O(n ^ 2). Which means, in worst case, the delegate you provided will be called n ^ 2 times, where n is the number of items in list. Delegate is like pointer to function.
It passes the two objects it wishes to compare, and the delegate you provided will return with -1, 0, or 1. If its -1 it means that p1 is lesser then p2, if 0 it means both objects are same, if 1 it means p1 is greater then p2. So, in the end, the delegate you provide and the values it returns will decide whether the list contains objects in descending or ascending order.
Lets divide the problem so that you can understand each piece separately:
The Sort method:
This one takes a delegate, that contains the "how to" compare two elements of the list.
As soon as you teach the list how to compare to elements, then it can sort all elements, by comparing them in pairs.
The inline delegate
A inline delegate is the declaration of method, that does something.
delegate(Person p1, Person p2) { return p1.age.CompareTo(p2.age);
This delegate is telling how to compare two Person objects. You are telling this to the compiler: to compare p1 with p2, you should compare p1.age with p2.age.
Joining things
The following line of code contains both elements, the sort method, and the "how to" compare two People objects.
people.Sort(delegate(Person p1, Person p2) { return p1.age.CompareTo(p2.age); });
So now it knows how to sort the list.

How to Implement IEqualityComparer<PointF> With Tolerance

This question is similar to the one here.
We all know what PointF is, don't we? This is the data structure:
public struct PointF
{
public float X;
public float Y;
}
How to implement IEqualityComparer<PointF> with tolerance? Let's say my Equals code is like this
public const float Epsilon = 0.01; //say
public bool Equals(PointF pt1, PointF pt2)
{
return Math.Abs(pt1.X-pt2.X)<Epsilon && Math.Abs(pt1.Y-pt2.Y)<Epsilon;
}
Question: How to implement the correct GetHashCode so that for a dictionary of PointF, I will access the element correctly?
I crack my head a few days but still can't find a satisfactory solution.
Instead of defining the tolerance by the distance, you could place the points in a grid.
If two points are in the same cell, they're considered equal and have the same hash code.
public bool Equals(PointF pt1, PointF pt2)
{
return GetCell(pt1.X) == GetCell(pt2.X)
&& GetCell(pt1.Y) == GetCell(pt2.Y);
}
public int GetHashCode(PointF pt)
{
return GetCell(pt.X) ^ GetCell(pt.Y);
}
private static int GetCell(float f)
{
return (int)(f / 10); // cell size is 10 pixels
}
Thesis: There is no implementation of Equals and GetHashCode that meets your requirements.
Proof: Consider the following three points, A, B, and C:
As per your requirements,
Equals(A, B) == true // (i)
Equals(B, C) == true // (ii)
Equals(A, C) == false // (iii)
GetHashCode(A) == GetHashCode(B) // (iv)
GetHashCode(B) == GetHashCode(C) // (v)
GetHashCode(A) != GetHashCode(C) // (vi)
But from (iv) and (v) follows
GetHashCode(A) == GetHashCode(C)
and thereby
Equals(A, C) == true
which contradicts (iii) and (vi).
Since Equals and GetHashCode cannot return different values for the same arguments, there is no implementation that meets your requirements.
q.e.d.
I don't think it's possible because you could have an infinite sequence of values that are equal (within tolerance) to the previous and next value in the sequence but not any other value and GetHashCode would need to return an identical value for all of them.
Well, the answer based on grids is good, but sometimes you need to group the close points anyway, even if they are not in the same grid cell. My approach is to implement this with a grouping: two points are in the same group if either they are close or there is a sequence of close points connecting them. This semantics cannot be done with a proper IEqualityComparer, because it needs to know all the items in advance before producing the groups. So I've done a simple LINQ-style operator GroupByCluster, which basically achieves this.
The code is here: http://ideone.com/8l0LH. It compiles on my VS 2010, but fails to compile on Mono because HashSet<> cannot be implicitly converted to IEnumerable<> (why?).
The approach is generic and thus not very efficient: it's quadratic on input size. For the concrete types it can be made more efficient: for example, for T = double we can just sort the input array and have O(n log n) performance. The analogous though more complicated trick is applicable for 2D points as well.
Note aside: your initial proposition is impossible to implement with IEqualityComparer, since your "approximate equality" is not transitive (but the equality in IEqualityComparer has to be so).

C#: Sorting with anonymous function

Let's say I have a list of objects, and I want to sort it by the items DateModified property. Why can't I use a delegate like this? How should I sort these by DateModified if not as shown below:
public string SortByDateModified(List<CartItem> items)
{
items.Sort(new Func<CartItem, CartItem, bool>((itemA, itemB) =>
{
return itemA.DateModified < itemB.DateModified;
}));
}
Why not use a lambda expression?
public string SortByDateModified(List<CartItem> items)
{
items.Sort((a, b) => a.DateModified.CompareTo(b.DateModified));
}
If you don't want to use lambdas or greater than .NET 2.0, use this:
public string SortByDateModified(List<CartItem> items)
{
items.Sort(delegate(CartItem itemA, CartItem itemB)
{
return itemA.DateModified.CompareTo(itemB.DateModified);
});
}
In my experience, in environments such as Unity, lambdas and even delegates can cause crashes or problems, especially on platforms like iOS. In that case you would want to make your sorter a separate function like so:
int SortCartItemFunction(CartItem itemA, CartItem itemB)
{
return itemA.DateModified.CompareTo(itemB.DateModified);
}
Then you could pass it to your sort call like this:
items.Sort(SortCartItemFunction);
The Sort method takes a delegate called Comparison<T>. You're trying to pass in a Func<int, int, bool>, which is itself a delegate. There is no conversion between the delegate Func<int, int, bool> and the delegate Comparison<T>.
You can, however, use a lambda expression.
items.Sort((a, b) => a.DateModified.CompareTo(b.DateModified));
Indeed, you use this very lambda expression and pass it into the Func<int, int, bool> constructor*. However, there is no need. A lambda expression can be converted into any delegate whos signature matches - that is (a, b) => a.DateModified.CompareTo(b.DateModified) can be assigned to something typed Func<int, int, int> or something typed Comparison<T>. In this case we pass it in to something which expects a Comparison<T>.
* With one minor adjustment. Sort expectes an integer as a return type. Negative values indicate less than, 0 indicates equal, and positive values indicate greater than.
bool is not useful in such a delegate, usually int is used because you need 3 values to represent the results of the comparison, less than, equal and greater than. .NET collections usually (if not always) assume -1 means less than, 0 means equal and 1 means greater than.
You would then, in your delegate, have to check if value x is less, equal or greater than value y. An interesting thing to note here is that if you flip the results, for example compare y with x instead you will sort in the opposite direction.
For the easiest way to sort the dates, check JohnC's answer, or Sam's.

Categories

Resources