I intend to ask about generic operator+ overloading but not in typical "can I do operator+ for generic type" way.
Questions are on the bottom
I recently started to create matrix class in C# and after a while It came to me that I cannot do simple T + T !
Thus, I googled and googled and found several workarounds.
Create Expression link
Create abstract class abstract class Matrix<T>{//some code}. Create 'protected virtual method Add(T itemToAdd)' and then create
operator like this : T operator+(T item1, T item2){return item1.Add(item2);}(most posts on stack) and then inherit this method in class Matrix : Matrix<int> here
Use method Add such as : T Add(T first, T second){ dynamic output = first + second; return output;} (somewhere on stack)
First one just does not suited me so I tried second one but then I run onto serious problems like:
(A LOT of )repetative code - I created 4 classes for : int, double, long, Complex - my own type
Creating multiple extension methods and so on.
Third one is just so unsafe that I rejected it immidietlay.
After my struggling I came to realise : 'Why don't I use RTTI and reflection?' I know, it is expensive in running time but why not use static constructor to do this?
Here is my idea (pseudocode):
class Matrix<T>{
static Func<T,T,T> Add;
static Matrix
{
if(T is int)
Add = (first,second) = > ((int)first)+((int)second);
else if(T is long)
Add = (first,second) = > ((long)first)+((long)second);
// and so on for built-in types
else
{ // T is not built-in type
if(typeof(T).GetMethods().Contains("op_Addition"))
{
Add = (first,second) => typeof(T).getMethod("op_Addition").invoke(first,second);
}
}
}
I know that reflection is costly but it will do it only one time (per type)!
And before you start argue : I am going to code T is int like this :
var type = typeof(T);
if(type==typeof(int)) // code
I am aware that I cannot explicitly convert T to int but there must be some sort of 'work around'. Problem is that (for example) Int32 has not explicit 'method' for operator+ hence, reflection is not of much use.
After all that introduction I have two questions :
Is it a good approach or do you see major flaws in it?
Is it doable? I don't want to start creating code without knowing for sure that my lambda function WILL work.
EDIT 1+2
I changed my code to generic.
I figured that maybe you need an usage of my class, here you are :
Matrix<int> matrix = new Matrix(1,1); // creates int-based matrix
Matrix<MyClass> matrix2 = new Matrix(1,1); // creates some other type matrix
ANSWER
based on dasblinkenlight's answer I managed to do this :
public interface ITypeTratis<T>
{
T Add(T a, T b);
T Mul(T a, T b);
T Sub(T a, T b);
T Div(T a, T b);
bool Eq(T a, T b);
}
public class IntTypeTratis : ITypeTratis<int>
{
//code for int
}
public class DoubleTypeTratis : ITypeTratis<double>
{
//code for double
}
internal class TypeTraits<T> : ITypeTratis<T>
{
public Func<T, T, T> AddF;
public Func<T, T, T> MulF;
public Func<T, T, T> DivF;
public Func<T, T, T> SubF;
public Func<T, T, bool> EqF;
public T Add(T a, T b) => AddF(a, b);
public bool Eq(T a, T b) => EqF(a, b);
public T Mul(T a, T b) => MulF(a, b);
public T Sub(T a, T b) => SubF(a, b);
public T Div(T a, T b) => DivF(a, b);
}
public class Matrix<T>
{
private static IDictionary<Type, object> traitByType = new Dictionary<Type, object>()
{
{typeof (int), new IntTypeTratis()},
{typeof (double), new DoubleTypeTratis()}
};
static Matrix()
{
Debug.WriteLine("Robie konstruktor dla " + typeof(T));
var type = typeof(T);
if (!traitByType.ContainsKey(type))
{
MethodInfo add, sub, mul, div, eq;
if ((add = type.GetMethod("op_Addition")) == null)
throw new NotSupportedException("Addition is not implemented");
if ((sub = type.GetMethod("op_Subtraction")) == null)
throw new NotSupportedException("Substraction is not implemented");
if ((mul = type.GetMethod("op_Multiply")) == null)
throw new NotSupportedException("Multiply is not implemented");
if ((div = type.GetMethod("op_Division")) == null)
throw new NotSupportedException("Division is not implemented");
if ((eq = type.GetMethod("op_Equality")) == null)
throw new NotSupportedException("Equality is not implemented");
var obj = new TypeTraits<T>
{
AddF = (a, b) => (T)add.Invoke(null, new object[] { a, b }),
SubF = (a, b) => (T)sub.Invoke(null, new object[] { a, b }),
MulF = (a, b) => (T)mul.Invoke(null, new object[] { a, b }),
DivF = (a, b) => (T)div.Invoke(null, new object[] { a, b }),
EqF = (a, b) => (bool)eq.Invoke(null, new object[] { a, b })
};
traitByType[type] = obj;
}
}
}
And this is exactly what I was looking for.
Yes, your approach will work fine.
Your static constructor will run for each type parameter T, ensuring that Add is set correctly.
You may want to separate out the addition logic into a separate class outside your matrix, and use that class to run operations based on type for your matrix. For example, if you also need multiplication, you could build a ITypeTraits<T> interface that has Add and Multiply:
public interface ITypeTraits<T> {
T Add(T a, T b);
T Mul(T a, T b);
}
Now you can build implementations of ITypeTraits<T> for individual types, e.g.
public class IntTypeTraits : ITypeTraits<int> {
public int Add(int a, int b) { return a+b; }
public int Mul(int a, int b) { return a*b; }
}
public class LongTypeTraits : ITypeTraits<long> {
public long Add(long a, long b) { return a+b; }
public long Mul(long a, long b) { return a*b; }
}
... // and so on
make a dictionary out of them
static readonly IDictionary<Type,object> traitByType = new Dictionary<Type,object> {
{typeof(int), new IntTypeTraits() }
, {typeof(long), new LongTypeTraits() }
... // and so on
};
and get the one you need to perform operations:
ITypeTraits<T> traits = (ITypeTraits<T>)traitByType(typeof(T));
T first = ...
T second = ...
T sum = traits.Add(first, second);
T prod = traits.Mul(first, second);
We can do this natively in C# 11 / .NET 7 (or above):
class Matrix<T> where T : INumber<T> // or just IAdditionOperators<T,T,T>
{
T x, y, z; // just to show we can do things
public T Sum() => x + y + z;
}
What is wrong with #3? You can just check for type, like so:
public abstract class Matrix<T>
{
public static HashSet<Type> AllowAdd = new HashSet<Type>
{
typeof(int),
typeof(long),
typeof(string),
typeof(double),
};
public T Add<T>(T first, T second)
{
if(!AllowAdd.Contains(typeof(T)))
{
throw new Exception(string.Format("Cannot preform addition for type: {0}", typeof(T).Name));
}
dynamic result = (dynamic)first + (dynamic)second;
return (T)result;
}
}
Bulding on dasblinkenlight's answer, here's my version of it. The benefit is that it doesn't need a dictionary lookup, instead making the type system do it. Should be faster, I think, but I haven't measured it. Also a bit less typing.
public abstract class MatrixBase
{
protected static class OperationDict<T>
{
private static Func<T,T,T> _notSupported = (a, b) => { throw new NotSupportedException(string.Format("Type {0} not supported for Matrix operations!", typeof(T))); };
public static Func<T, T, T> Add = _notSupported;
public static Func<T, T, T> Multiply = _notSupported;
}
static MatrixBase()
{
OperationDict<int>.Add = (a, b) => a + b;
OperationDict<int>.Multiply = (a, b) => a * b;
OperationDict<decimal>.Add = (a, b) => a + b;
OperationDict<decimal>.Multiply = (a, b) => a * b;
// Etc. for all supported types
}
}
public class Matrix<T> : MatrixBase
{
public T DoAdd(T a, T b)
{
return OperationDict<T>.Add(a, b);
}
}
I think you are on the right path, in order to avoid using reflection, you are required to somehow inform the compiler that you know "T" has the "+" operator, however, this feature does not yet exist in C#, so this is impossible to implement without runtime type checking or imposing other constraints.
If you don't care about the performance, you could use dynamic:
(dynamic)first + (dynamic)second
but that will take several reflection performance hits in every operation
Or you could use some other more complex approach that caches the specific methods in a dictionary, but you won't escape calling at least .GetType() in your add's implementation
Related
Consider the following code in C#.
public int Foo(int a)
{
// ...
}
// in some other method
int? x = 0;
x = Foo(x);
The last line will return a compilation error cannot convert from 'int?' to 'int' which is fair enough. However, for example in Haskell there is Maybe which is a counterpart to Nullable in C#. Since Maybe is a Functor I would be able to apply Foo to x using fmap. Does C# have a similar mechanism?
We can implement such functionality ourselves:
public static class FuncUtils {
public static Nullable<R> Fmap<T, R>(this Nullable<T> x, Func<T, R> f)
where T : struct
where R : struct {
if(x != null) {
return f(x.Value);
} else {
return null;
}
}
}
Then we can use it with:
int? x = 0;
x = x.Fmap(Foo);
It will thus call the function Foo if x is not null. It will wrap the result back in a Nullable<R>. In case x is null, it will return a Nullable<R> with null.
Or we can write a more equivalent function (like fmap in Haskell) where we have a function Fmap that takes as input a Func<T, R> and returns a Func<Nullable<T>, Nullable<R>> so that we can then use it for a certain x:
public static class FuncUtils {
public static Func<Nullable<T>, Nullable<R>> Fmap<T, R>(Func<T, R> f)
where T : struct
where R : struct {
return delegate (Nullable<T> x) {
if(x != null) {
return f(x.Value);
} else {
return null;
}
};
}
}
We can then use it like:
var fmapf = FuncUtils.Fmap<int, int>(Foo);
fmapf(null); // -> null
fmapf(12); // -> Foo(12) as int?
Functor
Not only can you turn Nullable<T> into a functor, but C# actually understands functors, enabling you to write something like this:
x = from x1 in x
select Foo(x1);
If you prefer method call syntax, that's also possible:
x = x.Select(Foo);
In both cases, you need an extension method like this:
public static TResult? Select<T, TResult>(
this T? source,
Func<T, TResult> selector) where T : struct where TResult : struct
{
if (!source.HasValue)
return null;
return new TResult?(selector(source.Value));
}
Monad
Not only does C# understand functors, but it understands monads as well. Add these SelectMany overloads as well:
public static TResult? SelectMany<T, TResult>(
this T? source,
Func<T, TResult?> selector)
where T : struct
where TResult : struct
{
if (!source.HasValue)
return null;
return selector(source.Value);
}
public static TResult? SelectMany<T, U, TResult>(
this T? source,
Func<T, U?> k,
Func<T, U, TResult> s)
where T : struct
where TResult : struct
where U : struct
{
return source
.SelectMany(x => k(x)
.SelectMany(y => new TResult?(s(x, y))));
}
This enables you to write queries like this:
var result = from x in (int?)6
from y in (int?)7
select x * y;
Here, result is an int? containing the number 42.
If you have an extension method:
public int Foo(this int a)
{
// ...
}
you can do:
// in some other method
int? x = 0;
x = x?.Foo();
The ?. operator will ensure Foo is called only if x is not null. If x is null, it is not called (a null of the return type is used instead).
Otherwise, the canonical way to write it is naturally:
x = x.HasValue ? Foo(x.Value) : (int?)null;
Of course you can create your own Maybe infrastructure if you will (Willem Van Onsem's answer).
I'm trying to implement a c++ like template with C# generics and policy pattern based on this answer
This is a sample of the pattern:
interface ISomePolicy<T,U>
{
void _doSomething(U u);
}
class MyClass<T,U>:
ISomePolicy<int, double>,
ISomePolicy<int, int>
{
internal T myElement {get;set;}
public MyClass(T Element) {
myElement = Element;
}
void ISomePolicy<int, double>._doSomething(double u)
{
Console.WriteLine("this is int, double");
}
void ISomePolicy<int, int>._doSomething(int u)
{
Console.WriteLine("this is int, int");
}
}
static class MyClassExtension
{
//What I want to do
public static void doSomething<P, T, U>(this P oTh, U u) where P : MyClass<T, U>, ISomePolicy<T, U>
{
oTh._doSomething(u);
}
}
My intended behaviour is like this:
MyClass<int, double> oClass = new MyClass<int, double>(3);
oClass.doSomething(0.5); //This works
oClass.doSomething(1); //This works
oClass.doSomething("This should fail"); //Breaks at compile time
MyClass<string, double> oClass1 = new MyClass<string, double>("sadfsd"); //Not implemented, wasn't able to prevent the construction.
oClass1.doSomething(0.4); //Breaks at compile time
But so far I wasn't able to make .net accept Generic Extension with less arguments than parameters
I can call the interface explicitly, which is horrible verbose defeating the purpose of all this.
oClass.doSomething < MyClass<int, double>,int,double>(0.5);
I thought of working that around with a wrapper:
static class MyClassExtension{
private static void wrappedDoSomething<P, T, U>(this P oTh, U u)
where P : MyClass<T, U>, ISomePolicy<T, U>
{
oTh._doSomething(u);
}
public static void doSomething<T, U>(this MyClass<T, U> oTh, U u)
{
oTh.wrappedDoSomething<MyClass<T, U>, T, U>(u);
}
}
But the wrapper can't resolve both types for the wrapped function, failing with:
Error 1 The type 'MyClass' cannot be used as type parameter 'P'
in the generic type or method
'MyClassExtension.wrappedDoSomething(P, U)'. There is no
implicit reference conversion from 'MyClass' to
'ISomePolicy'
Any insights to fix the parameters issue or redesign all this are appreciated.
For context this would be used to wrap I/O translators. T in my case would be the target I/O format, and U the object representation of that data used by my framework.
I'm aware that this can be easily achieved with delegates or interfaces, but the objective is that the framework user easily instantiates the desired translation, and if an implementation doesn't exists, it can be trivially added to a common interface.
EDIT: Resolving a generic method from inside another generic method/class neither seems to work on mono.
Usually, policies should not contain data. For example,
interface ISomePolicy<T, U>
{
void _doSomething(T t, U u);
}
struct SomePolicyImplementation :
ISomePolicy<int, double>,
ISomePolicy<int, int>,
ISomePolicy<double, double>
{
void ISomePolicy<int, int>._doSomething(int t, int u)
=> Console.WriteLine("this is int, int");
void ISomePolicy<int, double>._doSomething(int t, double u)
=> Console.WriteLine("this is int, double");
void ISomePolicy<double, double>._doSomething(double t, double u)
=> Console.WriteLine("this is double, double");
}
static class SomePolicyExtension
{
public static void doSomething<P, T, U>(this P policy, T t, U u)
where P : struct, ISomePolicy<T, U>
=> policy._doSomething(t, u);
}
If you would like to combine policies and data then you may consider different interface
interface IEmbeddedPolicy<U>
{
void _doSomething(U u);
}
class MyClass<T> :
IEmbeddedPolicy<double>,
IEmbeddedPolicy<int>
{
public T Value { get; }
public MyClass(T value) { this.Value = value; }
void IEmbeddedPolicy<int>._doSomething(int u)
=> Console.WriteLine("this is T, int");
void IEmbeddedPolicy<double>._doSomething(double u)
=> Console.WriteLine("this is T, double");
}
static class EmbeddedPolicyExtension
{
public static void doSomething<E, U>(this E embedded, U u)
where E : IEmbeddedPolicy<U>
=> embedded._doSomething(u);
}
Or combination of these two concepts
class MySuperClass<P, T>:
IEmbeddedPolicy<double>,
IEmbeddedPolicy<int>
where P: struct, ISomePolicy<T, double>, ISomePolicy<T, int>
{
public T Value { get; }
public MySuperClass(T value) { this.Value = value; }
void IEmbeddedPolicy<int>._doSomething(int u)
=> new P()._doSomething(this.Value, u);
void IEmbeddedPolicy<double>._doSomething(double u)
=> new P()._doSomething(this.Value, u);
}
Usage:
// independent policy
var policy = new SomePolicyImplementation();
policy.doSomething(5, 6);
policy.doSomething(5, 6.7);
policy.doSomething(5.3, 6.7);
// embedded policy
var my = new MyClass<int>(54);
my.doSomething(5);
my.doSomething(89.7);
// combination
var x = new MySuperClass<SomePolicyImplementation, int>(53);
x.doSomething(9);
x.doSomething(18.3);
Tried your code, but even simple calls did not work out of box. Main problem is that MyClass contains unknown element type 'myEement' - that type cannot be deduced from function call parameters. However - if you make a generalization and omit object type - your sample will work in out of box manner:
using System;
using System.Collections.Generic;
interface ISomePolicy<U>
{
void _doSomething(U u);
}
public class MyClass<U> :
ISomePolicy<double>,
ISomePolicy<int>
{
internal object myEement { get; set; }
public MyClass(object Element)
{
myEement = Element;
}
void ISomePolicy<double>._doSomething(double u)
{
Console.WriteLine("this is double");
}
void ISomePolicy<int>._doSomething(int u)
{
Console.WriteLine("this is int");
}
}
static class MyClassExtension
{
public static void doSomething<P, U>(this P oTh, U u) where P : ISomePolicy<U>
{
oTh._doSomething(u);
}
}
class Program
{
static void Main()
{
MyClass<double> oClass = new MyClass<double>(3);
oClass.doSomething(0.5); //This works
oClass.doSomething(1); //This works
//oClass.doSomething("Will not work");
}
}
What is up to myEement (or you probably meant myElement) - you can get's it's type at run-time if necessary.
myElement.GetType(), or cast to it - e.g.
if( myElement is int ) DoSomethingWithInt( (int) myElement );
However - reflection always might slow down your execution. If you don't intend to create super heavy class hierarchy with huge amount of instances - then this should be sufficient for your needs.
I have a client application that uses classes (and enums) from an external dll which is loaded at runtime and reflected. I know what methods I am expecting to find in the dll and what I am expecting its enums to be called.
I would like to create a delegate that I can use in the client application and which is created from the reflected method at runtime. This approach works when the delegate just has "standard" types, but how can I get this to work if the dll method takes an enum? I can't declare the enum in the delegate as an object since it's a value type, trying the Enum or int does not seem to work either. Is there a way around this? Any help gratefully received!
// e.g. external code
namespace test2
{
public static class test2
{
public static int calc(int a, int b, testEnum c)
{
if (c == testEnum.add) return a + b;
else return a - b;
}
public static int add(int a, int b)
{
return a + b;
}
}
public enum testEnum
{
add, subtract
}
}
// my client code
namespace test1
{
public class TestClient
{
private static Assembly _assembly;
public static void SetUp()
{
const string externalDll = ".../test2.dll";
Assembly assembly = Assembly.LoadFrom(externalDll);
AppDomain.CurrentDomain.Load(assembly.GetName());
_assembly = assembly;
}
private delegate int _add(int a, int b);
private _add add;
private delegate int _calc(int a, int b, ??? c); // nothing works here
private _calc calc;
public void Run()
{
SetUp();
add = GetExpectedFunction<_add>("add");
int three = add(1, 2); // OK
calc = GetExpectedFunction<_calc>("calc"); // not OK
// intended usage
var reflectedEnum = ReflectMe("testEnum", "add");
int threeAgain = calc(1, 2, reflectedEnum);
}
public static T GetExpectedFunction<T>(string functionName) where T : class
{
try
{
if (!typeof(T).IsSubclassOf(typeof(Delegate))) throw new ApplicationException("GetExpectedFunction must return a delegate!");
var foundMethod = _assembly.GetType("test2.test2").GetMethod(functionName, BindingFlags.Public | BindingFlags.Static);
return (T)(object)Delegate.CreateDelegate(typeof(T), foundMethod);
}
catch (Exception e)
{
// "Error binding to target method!"
}
}
}
}
You can bind a delegate with object type to a method taking an enum by creating, at runtime, a dynamic method call with LINQ Expression, and adding data conversions for parameters whose types don't match:
public static T GetExpectedFunction<T>(string functionName) where T : class {
try {
if (!typeof(T).IsSubclassOf(typeof(Delegate))) throw new ApplicationException("GetExpectedFunction must return a delegate!");
var foundMethod = Type.GetType("test2.test2").GetMethod(functionName, BindingFlags.Public | BindingFlags.Static);
var inv = typeof(T).GetMethod("Invoke");
var parameters = inv.GetParameters().Zip(foundMethod.GetParameters(), (a, b) => new {
PassedIn = a.ParameterType
, Reflected = b.ParameterType
, Parameter = Expression.Parameter(a.ParameterType)
}).ToList();
if (parameters.All(p => p.PassedIn == p.Reflected)) {
// Bind directly
return (T)(object)Delegate.CreateDelegate(typeof(T), foundMethod);
}
var call = Expression.Call(foundMethod, parameters.Select(
p => p.PassedIn==p.Reflected
? (Expression)p.Parameter
: Expression.Convert(p.Parameter, p.Reflected)
));
return (T) (object) Expression.Lambda(typeof(T), call, parameters.Select(p => p.Parameter)).Compile();
} catch (Exception e) {
// "Error binding to target method!"
return null;
}
}
This implementation pairs up types from the reflected and the delegate methods (see parameters variable), and creates ParameterExpression objects for types that come from the delegate. Then it checks if all parameter types match up (the parameters.All(...) part). This is an optimization for situations when conversions are unnecessary.
If at least one conversion is necessary, the code creates a method call that substitutes the original parameter expressions with conversion expressions where types do not match up, creates a lambda of the requested delegate type, compiles it, and returns it to the caller.
For your code this dynamic method would look like this:
int dynamic_method(int a, int b, object c) {
return test2.test2(a, b, (testEnum)c);
}
There is one solution, you have to create faked Enum (it will be better if you create the exact enum), then you will pass as integer like this:
private delegate int _add(int a, int b);
private _add add;
private delegate int _calc(int a, int b, FakedEnum c); // faked enum here
private _calc calc;
public enum FakedEnum
{
}
public void Run()
{
SetUp();
add = GetExpectedFunction<_add>("add");
int three = add(1, 2); // OK
calc = GetExpectedFunction<_calc>("calc"); // it will be ok
var result= calc(4, 6, (FakedEnum)0);
// intended usage
// var reflectedEnum = ReflectMe("testEnum", "add");
//int threeAgain = calc(1, 2, reflectedEnum);
}
Use dynamic keyword to declare your delegate parameter:
private delegate int _calc(int a, int b, dynamic c);
public class Racional<T>
{
private T nominator;
private T denominator;
public T Nominator
{
get { return nominator; }
set { nominator = value; }
}
public T Denominator
{
get { return denominator; }
set { denominator = value; }
}
public Racional(T nominator, T denominator)
{
this.nominator = nominator;
this.denominator = denominator;
}
public static Racional<int> operator *(Racional<int> a, Racional<int> b)
{
return ((int)(a.nominator + b.nominator, a.denominator + b.denominator));
}
public override string ToString()
{
return "(" + this.nominator + " " + this.denominator + ")";
}
}
I'm interested in this part :
public static Racional<int> operator *(Racional<int> a, Racional<int> b)
{
return ((int)(a.nominator + b.nominator, a.denominator + b.denominator));
}
What's wrong:
One of the parameters of a binary operator must be the containing type
How I can normaly code this part for mathematic operations?
The reason your code doesn't compile is explained by the compiler error. The containing type is a generic type definition, and a generic type constructed from such a type is not considered to be the same type.
I have a few questions:
Why must the Rational type be generic? A rational number is defined as a number that can be expressed as the quotient / fraction of two integers (where the denominator is not 0). Why not make the type non-generic and simply use int throughout? Or do you intend that the type be used for other integral types such as long and BigInteger? In that case, consider using something like Aliostad's suggestion if you want some code-sharing mechanism.
Why do you want the product of two rational numbers to be the equal to the sum of their numerators over the sum of their denominators? That doesn't make sense to me.
In any case, you appear to want to be able to 'generically' add two instances of an 'addable' type. Unfortunately, there currently isn't any way to express a 'has a suitable addition operator' constraint in C#.
Method #1: One workaround for this in C# 4 is to use the dynamic type to give you the desired "virtual operator" semantics.
public static Racional<T> operator *(Racional<T> a, Racional<T> b)
{
var nominatorSum = (dynamic)a.Nominator + b.Nominator;
var denominatorSum = (dynamic)a.Denominator + b.Denominator;
return new Racional<T>(nominatorSum, denominatorSum);
}
The operator will throw if the type doesn't have a suitable addition operator.
Method #2: Another (more efficient) way is to use expression-trees.
First, create and cache a delegate that can perform the addition by compiling the appropriate expression:
private readonly static Func<T, T, T> Adder;
static Racional()
{
var firstOperand = Expression.Parameter(typeof(T), "x");
var secondOperand = Expression.Parameter(typeof(T), "y");
var body = Expression.Add(firstOperand, secondOperand);
Adder = Expression.Lambda<Func<T, T, T>>
(body, firstOperand, secondOperand).Compile();
}
(The static constructor will throw if the type doesn't have a suitable addition operator.)
Then employ it in the operator:
public static Racional<T> operator *(Racional<T> a, Racional<T> b)
{
var nominatorSum = Adder(a.Nominator, b.Nominator);
var denominatorSum = Adder(a.Denominator, b.Denominator);
return new Racional<T>(nominatorSum, denominatorSum);
}
The issue here is you are defining an operator for Racional<int> in the class Racional<T>. This is not possible. The types are not the same, you can only define operator for Racional<T>.
Generics cannot express generalization of operators since they are defined only for a certain types. Solution is to create a class and inherit from Racional<int>:
public class IntRacional : Racional<int>
{
public static Racional<int> operator +(IntRacional a, IntRacional b)
{
return new Racional<int>()
{
Nominator = a.Nominator + b.Nominator,
Denominator = a.Denominator + b.Denominator
};
}
}
To solve your issue, you need to provide conversion functions from T to some type where operator+ is defined and vice versa. Assuming Int64 is big enough in most cases, this can be done this way:
public class Racional<T>
{
private T nominator;
private T denominator;
static Converter<T,Int64> T_to_Int64;
static Converter<Int64,T> Int64_to_T;
public static void InitConverters(Converter<T,Int64> t2int, Converter<Int64,T> int2t )
{
T_to_Int64 = t2int;
Int64_to_T = int2t;
}
public T Nominator
{
get { return nominator; }
set { nominator = value; }
}
public T Denominator
{
get { return denominator; }
set { denominator = value; }
}
public Racional(T nominator, T denominator)
{
this.nominator = nominator;
this.denominator = denominator;
}
public static Racional<T> operator *(Racional<T> a, Racional<T> b)
{
return new Racional<T>(
Int64_to_T(T_to_Int64(a.nominator) + T_to_Int64(b.nominator)),
Int64_to_T(T_to_Int64(a.denominator) + T_to_Int64(b.denominator)));
}
// By the way, should this not be * instead of + ???
//
// public static Racional<T> operator *(Racional<T> a, Racional<T> b)
// {
// return new Racional<T>(
// Int64_to_T(T_to_Int64(a.nominator) * T_to_Int64(b.nominator)),
// Int64_to_T(T_to_Int64(a.denominator) * T_to_Int64(b.denominator)));
// }
public override string ToString()
{
return "(" + this.nominator + " " + this.denominator + ")";
}
}
Of course, this has the drawback that you must provide the initialization of those converters somewhere at the program start, should look like this:
Racional<int>.InitConverters(x => (Int64)x, y => (int)y);
In a real program, you may know which possible replacements for T you are going to use. So one can provide those 3 or 4 calls in a static constructor like this:
public static Racional()
{
Racional<int>.InitConverters(x => (Int64)x, y => (int)y);
Racional<short>.InitConverters(x => (Int64)x, y => (short)y);
Racional<Int64>.InitConverters(x => (Int64)x, y => (Int64)y);
}
should be sufficient in most cases. Note that this converter initialization is repeated for all 3 types 3 times again, re-initializing the conversion functions multiple times again. In practice this should not make any trouble.
Is there any way to make a code like this work:
public class Func2<A, B>
{
private Func<A, B> f;
public Func2(Func<A, B> f)
{
this.f = f;
}
public object invoke(object obj, long l)
{
if (typeof(B) == typeof(long))
{
if (obj != null)
l = (long)obj;
return f((B)l); //error! cannot convert type 'long' to 'B'
} else {
return f((B)obj);
}
}
}
The problem here is that I cannot directly cast B to long without casting B to object first. I am trying to avoid at all costs having to box, as it would slow down a lot fast operations on functions. So is there any way to achieve this?
I know I could actually define a specialized Func2 to specifically handle the case of when B is a long. But as the arity of the function grows, the combination of longs and objects grow exponentially - and in the real use case I want also to support doubles !. Is there any way to support this without boxing? Maybe with unsafe code?
Thank you!
CauĂȘ
You can overload the method, and instead of casting the long value to A, you can cast the delegate to Func<long, B>:
public class Func2<A, B> {
private Func<A, B> f;
public Func2(Func<A, B> f) {
this.f = f;
}
public B invoke(long a) {
if (typeof(A) == typeof(long)) {
return (f as Func<long, B>)(a);
} else {
throw new NotSupportedException();
}
}
public B invoke(object a) {
return f((A)a);
}
}
Example:
Func2<long, string> f = new Func2<long, string>(l => l.ToString());
Console.WriteLine(f.invoke(42)); // calls the invoke(long) method
Console.WriteLine(f.invoke("x")); // calls the invoke(object) method
Just found out the answer ! : )
public object invoke(object obj, long l)
{
if (typeof(B) == typeof(long))
{
if (obj != null)
l = (long)obj;
Func<A, long> x = (Func<A, long>)(object)f;
return x(l);
} else {
return f((B)obj);
}
}
This way we don't have to autobox the long to object, but we actually cast the Func type to receive the long we specified!
As for why I am trying to do this, read the above comment, and I'd still be trying to find a best way to do this.
By now, we have the following Haxe code:
var f:Int->Int->Float = function(x:Int, y:Int) return x + y + 0.5;
var f2:Dynamic->Dynamic->Dynamic = f; // ok
var f3:Dynamic->Int->Dynamic = f; //also ok
f2(10, 30); // ok - this will box the 10 and 30
What I'm trying to do is create a Fun3 type that has an invoke call that will take both the boxed and unboxed arguments. If the underlying function really accepts unboxed types, it will try first to use them.