Convert template to generic - c#

Consider this simple code in C++/CLI
template <typename T>
T sum (T x, T y)
{
return x + y;
}
int main(array<System::String ^> ^args)
{
int a=4, b=6;
double x=2.3, y=5.2;
Console::WriteLine("Sum of two ints = {0}", sum(a, b));
Console::WriteLine("Sum of two doubles = {0}", sum(x, y));
return 0;
}
Output:
Sum of two ints = 10
Sum of two doubles = 7.5
How can I do this in C# using generics?

You can't. There is no way to apply a generic constraint in C# that will ensure that the given generic type will have a suitable overload of the + operator.
You can remove all static type checking and use reflection or similar to attempt to call the + operator of the given generic type at runtime, realizing that it will simply throw a runtime exception if no applicable operator exists, but that is not equivalent to the C++ code you provided.

There's no simple way of doing it with generics, because generics are not templates. You can do it if you supply the operator yourself, like this:
static T binary_apply<T>(T a, T b, Func<T,T,T> add) {
return add(a, b);
}
int a = 4, b = 6;
double x = 2.3, y = 5.2;
Console.WriteLine("Sum of two ints = {0}", binary_apply(a, b, (i,j)=>i+j));
Console.WriteLine("Sum of two doubles = {0}", binary_apply(x, y, (i,j)=>i+j));
Of course this defeats the purpose of having add<T>() in the first place, because you pass an implementation of the addition as a lambda. You can do this dynamically, too, but that is not the same as having the addition resolved by the compiler:
static T add<T>(T a, T b) {
var p0 = Expression.Parameter(typeof(T));
var p1 = Expression.Parameter(typeof(T));
var ae = Expression.Add(p0, p1);
var f = (Func<T,T,T>)Expression.Lambda(ae, p0, p1).Compile();
return f(a, b);
}
int a = 4, b = 6;
double x = 2.3, y = 5.2;
Console.WriteLine("Sum of two ints = {0}", add(a, b));
Console.WriteLine("Sum of two doubles = {0}", add(x, y));
Demo on ideone.

Related

Value Tuple initialization is counter-intuitive

In the Sunday evening I have been watching some conferences this time I get hands on this one Conference Link
Where I found out pretty interesting think there is simple code example:
struct Point
{
private double x;
public double X { get => x; set => x = value; }
private double y;
public double Y { get => y; set => y = value; }
public Point(double x, double y) => (this.x, this.y) = (x, y);
public void SwapCode() => (X, Y) = (Y, X);
}
In Main:
var point = new Point(10.0, 11.0);
Console.WriteLine($"x: {point.X}, y: {point.Y}");
point.SwapCode();
Console.WriteLine($"x: {point.X}, y: {point.Y}");
And there is output of this :
x: 10, y: 11
x: 11, y: 10
So there is some questions:
How does it works ?
What I mean by that is Tuples should be translate into Tuple<T, K> which should be initialize with copy of the values but there it assign values to the variables at least for me it's kind of counter intuitive.
And i wonder if it's just sugar syntax think or there is happen some magic under this what make perfect sense but I can't spot it out?
Firstly structs should be immutable. Even though you can do this, you probably shouldn't.
Secondly, your SwapCode is actually doing this, as seen here.
public void SwapCode()
{
double num = Y;
double num2 = X;
double num4 = X = num;
num4 = (Y = num2);
}
Yeah, it's a little strange. However, it's just a little syntactic magic introduced in C#7. What it is actually doing is using a deconstruct method (the terminology .Net uses) to provide a set of out arguments for each of the params you want to extract. In this case, it's the properties/field you supplied!
To see it a little clearer, consider these two functionally equivalent code blocks
(int x, int y) asd = (1, 2); // create a Value Tuple
(int x, int y) = asd; // deconstruct it
(x, y) = (x, y); // assign to the deconstructed type
// All the above now has the swapped values
// they are all pointing to the same variables/memory
// You could even take this further by
x = 10;
y = 11;
// Once again, x and y, asd, and (x, y) all have the same values
// Because they are the same
// ----------------------------------------------------
int x = 1;
int y = 2;
(x, y) = (y, x); // we are just deconstructing our original variables
// All the above now has the swapped values
// they are all pointing to the same variables/memory
Note : As you can see, this is also a slightly more succinct way of swapping 2 variables as you don't have to use a temp variables, your friendly CLR does it for you
Anyway, you shouldn't be doing this with a struct anyway, they really should be immutable for various reasons

How can I combine two functions into a single one using generics?

Say I have the following functions:
public int Compute(int a, int b, int c)
{
return (a + b +c)/3;
}
public double Compute(double a, double b, double c)
{
return ((a + b + c) / 3.0) / 209;
}
I hope the difference is obvious. A double value needs to be divided by 209 (a constant value) while an integer is not.
What is the best way to combine these two functions in a single one using generics?
I'm not sure it makes sense here.
Generics are the approach to avoid writing the similar code for different object types.
But in your case, I don't see any similar code which could be generalized so keeping the functions different solves the task better.
Short Answer
You cannot turn it into one function.
Long Answer
The only common code you have is this:
return (a + b +c)/
You could use generics and do this at best (not possible with C#):
public static T Compute<T>(T a, T b, T c, T divisorSmall, int divisor)
{
return ((a + b + c) / divisorSmall) / divisor;
// Results in compiler error: Error CS0019 Operator '+' cannot be
// applied to operands of type 'T' and 'T'
}
and use it like this:
Compute(1, 2, 3, 3, 1); // For integers
Compute(1.0, 2.0, 6.0, 3.0, 209); // For doubles
But you cannot do that because you cannot restrict the type T to support arithmetic operation or restrict T to be numeric.
Also, even if it was possible, you do not gain much in this specific case because look how clumsy the usage looks in my hypothetical solution.
You shouldn't do it with generics, but you can test if a, b and c are ints and then select your operation:
private double Compute(double a, double b, double c)
{
/* check if a, b and c are integers int if true double if false */
return (a % 1 == 0 && b % 1 == 0 && c % 1 == 0) ? (a + b + c) / 3 : ((a + b + c) / 3.0) / 209;
}
[TestMethod()]
public void Int()
{
int a = 1;
int b = 2;
int c = 3;
int result = (int)Compute(a, b, c);
int expected = (1 + 2 + 3) / 3;
Assert.AreEqual(expected, result);
}
[TestMethod()]
public void Double()
{
double a = 1.1;
double b = 2.2;
double c = 3.3;
double result = Compute(a, b, c);
double expected = ((1.1 + 2.2 + 3.3) / 3.0) / 209;
Assert.AreEqual(expected, result);
}
Both tests are passing
I have an idea. I can create a method generic which receives an Delegate for each case int and double. This version fiddle works https://dotnetfiddle.net/Q15bYK
public static void Main()
{
Func<double,double,double,double> x = (d1,d2,d3) => {return ((d1 +d2 + d3)/ 3.0) / 209;};
Func<int,int,int,int> y = (i1,i2,i3) => {return (i1 + i2 + i3)/ 3;};
var rsDouble = Compute<double>(1.0,2.0,3.0,x);
Console.WriteLine(rsDouble);
var rsInt = Compute<int>(1,2,3,y);
Console.WriteLine(rsInt);
}
public static T Compute<T>(T a, T b, T c, Func<T,T,T,T> action)
{
return action(a,b,c);
}
But this seems my answer make complicated the situation and I agree with other answers, generics are used to write the similar code for different object types, not to write different code for each parameters.

Get name of delegate method

Out of curiosity I've been looking into delegate methods and am interested in getting the name of the current delegate method that is being used (just for fun, really).
The code I have is as follows (with the current/desired outputs):
private delegate int mathDelegate(int x, int y);
public static void Main()
{
mathDelegate add = (x,y) => x + y;
mathDelegate subtract = (x,y) => x - y;
mathDelegate multiply = (x,y) => x * y;
var functions = new mathDelegate[]{add, subtract, multiply};
foreach (var function in functions){
var x = 6;
var y = 3;
Console.WriteLine(String.Format("{0}({1},{2}) = {3}", function.Method.Name, x, y, function(x, y)));
}
}
/// Output is:
// <Main>b__0(6,3) = 9
// <Main>b__1(6,3) = 3
// <Main>b__2(6,3) = 18
/// Desired output
// add(6,3) = 9
// subtract(6,3) = 3
// multiply(6,3) = 18
Does anyone know of any way(s) I could achieve this? Thanks.
Your methods are anonymous delegates, so the the compiler gives each of them a name that doesn't have any meaningful connection back to the variable name. If you want them to have better names then make them actual methods:
public int Add(int x, int y)
{
return x + y ;
}
etc. Then reference them by name:
var functions = new mathDelegate[]{this.Add, this.Subtract, this.Multiply};
Note that the this. is optional but illustrates that they are class members rather than local variables.

Return expression instead result

If I have function like this
double GetExpression(int x, int y, int z)
{
return x * y + z;
}
is it possible to modify it somehow, to not return result immediately only some object which is expression and then evaluate it this way:
var expression = GetExpression(1,2,3);
double result = expression.Execute() or expression.Evaluate()
other words just return function
?
Yes!
Func<double> GetExpression(int x, int y, int z)
{
return () => x * y + z;
}
use as:
var expression = GetExpression(1,2,3);
double result = expression();
Well, you could use delegates, and return a Func<double>:
Func<double> GetExpression(int x, int y, int z)
{
return () => x * y + z;
}
var expression = GetExpression(1,2,3);
double result = expression(); // Or expression.Invoke()
Is that what you were looking for?
Now each time you call expression() it will execute the code in the lambda expression. You can observe that if you use code which doesn't just return the same value each time. For example:
Func<int> GetExpression()
{
Random rng = new Random();
return () => rng.Next(10);
}
var expression = GetExpression();
for (int i = 0; i < 10; i++)
{
Console.WriteLine(expression());
}
That will print 10 random numbers in the range [0, 10). Note that this will only create one instance of Random (avoiding a common problem) - each time you call expression() it will call the Next() method on the same instance. The constructor for Random is called in the "normal" part of the method - it's not in the lambda expression. So that gets executed when you first call the GetExpression method (even if you never call expression() afterwards).
Note however that the arguments to your GetExpression were still passed by value though, and are captured by the lambda express. So consider this:
Func<int> GetExpression(int a, List<int> b)
{
return () => a + b.Count;
}
int x = 10;
List<int> list = new List<int> { 1, 2, 3 };
var expression = GetExpression(x, list);
Console.WriteLine(expression()); // 13
x = 20;
list.Add(100);
Console.WriteLine(expression()); // 14
Here the value of the list variable has been captured, so changes the the object that the value refers to are visible in the lambda expression, but changes to the x variable itself are not visible in the lambda expression. (Likewise if you had list = new List<int>(); that change wouldn't be visible...
To expand on Jon Skeet's answer, about capturing variables, if you didn't want to, you could do something like this:
double GetExpression(int x, int y, int z)
{
return x * y + z;
}
Func<int, int, int, double> expression = GetExpression;
for (int i = 0; i < 10; i++)
Console.WriteLine("{0}", expression(i, i+1, i+2));
Which avoids modifying the existing code (in case you wanted to point to a function you didn't have control over), and avoids capturing values outside of the lamda.

Sorting Complex Numbers

I have a struct called "Complex" in my project (I build it with using C#) and as the name of the struct implies, it's a struct for complex numbers. That struct has a built-in method called "Modulus" so that I can calculate the modulus of a complex number. The things are quite easy up to now.
The thing is, I create an array out of this struct and I want to sort the array according to the modulus of the complex numbers contained.(greater to smaller). Is there a way for that?? (Any algorithm suggestions will be welcomed.)
Thank you!!
Complex[] complexArray = ...
Complex[] sortedArray = complexArray.OrderByDescending(c => c.Modulus()).ToArray();
First of all, you can increase performances comparing squared modulus instead of modulus.
You don't need the squared root: "sqrt( a * a + b * b ) >= sqrt( c * c + d * d )" is equivalent to "a * a + b + b >= c * c + d * d".
Then, you can write a comparer to sort complex numbers.
public class ComplexModulusComparer :
IComparer<Complex>,
IComparer
{
public static readonly ComplexModulusComparer Default = new ComplexModulusComparer();
public int Compare(Complex a, Complex b)
{
return a.ModulusSquared().CompareTo(b.ModulusSquared());
}
int IComparer.Compare(object a, object b)
{
return ((Complex)a).ModulusSquared().CompareTo(((Complex)b).ModulusSquared());
}
}
You can write also the reverse comparer, since you want from greater to smaller.
public class ComplexModulusReverseComparer :
IComparer<Complex>,
IComparer
{
public static readonly ComplexModulusReverseComparer Default = new ComplexModulusReverseComparer();
public int Compare(Complex a, Complex b)
{
return - a.ModulusSquared().CompareTo(b.ModulusSquared());
}
int IComparer.Compare(object a, object b)
{
return - ((Complex)a).ModulusSquared().CompareTo(((Complex)b).ModulusSquared());
}
}
To sort an array you can then write two nice extension method ...
public static void SortByModulus(this Complex[] array)
{
Array.Sort(array, ComplexModulusComparer.Default);
}
public static void SortReverseByModulus(this Complex[] array)
{
Array.Sort(array, ComplexModulusReverseComparer.Default);
}
Then in your code...
Complex[] myArray ...;
myArray.SortReverseByModulus();
You can also implement the IComparable, if you wish, but a more correct and formal approach is to use the IComparer from my point of view.
public struct Complex :
IComparable<Complex>
{
public double R;
public double I;
public double Modulus() { return Math.Sqrt(R * R + I * I); }
public double ModulusSquared() { return R * R + I * I; }
public int CompareTo(Complex other)
{
return this.ModulusSquared().CompareTo(other.ModulusSquared());
}
}
And then you can write the ReverseComparer that can apply to every kind of comparer
public class ReverseComparer<T> :
IComparer<T>
{
private IComparer<T> comparer;
public static readonly ReverseComparer<T> Default = new ReverseComparer<T>();
public ReverseComparer<T>() :
this(Comparer<T>.Default)
{
}
public ReverseComparer<T>(IComparer<T> comparer)
{
this.comparer = comparer;
}
public int Compare(T a, T b)
{
return - this.comparer.Compare(a, b);
}
}
Then when you need to sort....
Complex[] array ...;
Array.Sort(array, ReverseComparer<Complex>.Default);
or in case you have another IComparer...
Complex[] array ...;
Array.Sort(array, new ReverseComparer<Complex>(myothercomparer));
RE-EDIT-
Ok i performed some speed test calculation.
Compiled with C# 4.0, in release mode, launched with all instances of visual studio closed.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
namespace TestComplex
{
class Program
{
public struct Complex
{
public double R;
public double I;
public double ModulusSquared()
{
return this.R * this.R + this.I * this.I;
}
}
public class ComplexComparer :
IComparer<Complex>
{
public static readonly ComplexComparer Default = new ComplexComparer();
public int Compare(Complex x, Complex y)
{
return x.ModulusSquared().CompareTo(y.ModulusSquared());
}
}
private static void RandomComplexArray(Complex[] myArray)
{
// We use always the same seed to avoid differences in quicksort.
Random r = new Random(2323);
for (int i = 0; i < myArray.Length; ++i)
{
myArray[i].R = r.NextDouble() * 10;
myArray[i].I = r.NextDouble() * 10;
}
}
static void Main(string[] args)
{
// We perform some first operation to ensure JIT compiled and optimized everything before running the real test.
Stopwatch sw = new Stopwatch();
Complex[] tmp = new Complex[2];
for (int repeat = 0; repeat < 10; ++repeat)
{
sw.Start();
tmp[0] = new Complex() { R = 10, I = 20 };
tmp[1] = new Complex() { R = 30, I = 50 };
ComplexComparer.Default.Compare(tmp[0], tmp[1]);
tmp.OrderByDescending(c => c.ModulusSquared()).ToArray();
sw.Stop();
}
int[] testSizes = new int[] { 5, 100, 1000, 100000, 250000, 1000000 };
for (int testSizeIdx = 0; testSizeIdx < testSizes.Length; ++testSizeIdx)
{
Console.WriteLine("For " + testSizes[testSizeIdx].ToString() + " input ...");
// We create our big array
Complex[] myArray = new Complex[testSizes[testSizeIdx]];
double bestTime = double.MaxValue;
// Now we execute repeatCount times our test.
const int repeatCount = 15;
for (int repeat = 0; repeat < repeatCount; ++repeat)
{
// We fill our array with random data
RandomComplexArray(myArray);
// Now we perform our sorting.
sw.Reset();
sw.Start();
Array.Sort(myArray, ComplexComparer.Default);
sw.Stop();
double elapsed = sw.Elapsed.TotalMilliseconds;
if (elapsed < bestTime)
bestTime = elapsed;
}
Console.WriteLine("Array.Sort best time is " + bestTime.ToString());
// Now we perform our test using linq
bestTime = double.MaxValue; // i forgot this before
for (int repeat = 0; repeat < repeatCount; ++repeat)
{
// We fill our array with random data
RandomComplexArray(myArray);
// Now we perform our sorting.
sw.Reset();
sw.Start();
myArray = myArray.OrderByDescending(c => c.ModulusSquared()).ToArray();
sw.Stop();
double elapsed = sw.Elapsed.TotalMilliseconds;
if (elapsed < bestTime)
bestTime = elapsed;
}
Console.WriteLine("linq best time is " + bestTime.ToString());
Console.WriteLine();
}
Console.WriteLine("Press enter to quit.");
Console.ReadLine();
}
}
}
And here the results:
For 5 input ...
Array.Sort best time is 0,0004
linq best time is 0,0018
For 100 input ...
Array.Sort best time is 0,0267
linq best time is 0,0298
For 1000 input ...
Array.Sort best time is 0,3568
linq best time is 0,4107
For 100000 input ...
Array.Sort best time is 57,3536
linq best time is 64,0196
For 250000 input ...
Array.Sort best time is 157,8832
linq best time is 194,3723
For 1000000 input ...
Array.Sort best time is 692,8211
linq best time is 1058,3259
Press enter to quit.
My machine is an Intel I5, 64 bit windows seven.
Sorry! I did a small stupid bug in the previous edit!
ARRAY.SORT OUTPEFORMS LINQ, yes by a very small amount, but as suspected, this amount grows with n, seems in a not-so-linear way. It seems to me both code overhead and a memory problem (cache miss, object allocation, GC ... don't know).
You can always use SortedList :) Assuming modulus is int:
var complexNumbers = new SortedList<int, Complex>();
complexNumbers.Add(number.Modulus(), number);
public struct Complex: IComparable<Complex>
{
//complex rectangular number: a + bi
public decimal A
public decimal B
//synonymous with absolute value, or in geometric terms, distance
public decimal Modulus() { ... }
//CompareTo() is the default comparison used by most built-in sorts;
//all we have to do here is pass through to Decimal's IComparable implementation
//via the results of the Modulus() methods
public int CompareTo(Complex other){ return this.Modulus().CompareTo(other.Modulus()); }
}
You can now use any sorting method you choose on any collection of Complex instances; Array.Sort(), List.Sort(), Enumerable.OrderBy() (it doesn't use your IComparable, but if Complex were a member of a containing class you could sort the containing class by the Complex members without having to go the extra level down to comparing moduli), etc etc.
You stated you wanted to sort in descending order; you may consider multiplying the results of the Modulus() comparison by -1 before returning it. However, I would caution against this as it may be confusing; you would have to use a method that normally gives you descending order to get the list in ascending order. Instead, most sorting methods allow you to specify either a sorting direction, or a custom comparison which can still make use of the IComparable implementation:
//This will use your Comparison, but reverse the sort order based on its result
myEnumerableOfComplex.OrderByDescending(c=>c);
//This explicitly negates your comparison; you can also use b.CompareTo(a)
//which is equivalent
myListOfComplex.Sort((a,b) => return a.CompareTo(b) * -1);
//DataGridView objects use a SortDirection enumeration to control and report
//sort order
myGridViewOfComplex.Sort(myGridViewOfComplex.Columns["ComplexColumn"], ListSortDirection.Descending);

Categories

Resources