Possible Duplicate:
Solution for overloaded operator constraint in .NET generics
I have a problem I’m working on, currently it is working for int
s but i want it to work for all classes that can be added using the +
operator. Is there any way to define this in the generic? For example,
public List<T> Foo<T>() where T : ISummable
Is there any way to do this?
EDIT:
Performance of passing in a delegate to do the summing instead of using += with a type of Int was 540% slower at best. Investigating possible other solution
Final solution:
Thank you all for your suggestions. I ended up with a solution which is not too slow and enforces the checking at compile time. I cannot take full credit as a colleague helped me arrive at this. Anyway, here it is:
Implement an interface with all of the required operators on it in the form of functions
public interface IFoo<InputType, OutputType>
{
//Adds A to B and returns a value of type OutputType
OutputType Add(InputType a, InputType b);
//Subtracts A from B and returns a value of type OutputType
OutputType Subtract(InputType a, InputType b);
}
Create the class you want to define, but instead of the Where clause, use a dependency injected instance of the IFoo interface. the OutputType will most often be double because the nature of the operations is mathematical.
public class Bar<T>
{
private readonly IFoo<T,double> _operators;
public Bar(IFoo<T, double> operators)
{
_operators = operators;
}
}
now when you use this class, you define the rules for operation like this:
private class Foo : IFoo<int, double>
{
public double Add(int a, int b)
{
return (double)(a+b);
}
public double Subtract(int a, int b)
{
return (double)(a-b);
}
}
then you would use it like this:
Foo inttoDoubleOperations = new Foo();
Bar myClass = new Bar(Foo);
that way all the operations are enforced at compile time :)
enjoy!
This is a pretty commonly requested new feature for C#: the ability to specify more generic parameter constraints than the ones we already have. Operators are among the most frequently asked. However, C# does not currently support this.
Possible workarounds:
Pass a delegate to any method that needs to do addition. This is the most type-safe option, but of course it’s annoying if you need to call such a method often. For example:
public class Generic<T> {
public void DoSomething(T anItem, T anotherItem, Func<T, T, T> add) {
// instead of
Blah(anItem + anotherItem);
// have to write:
Blah(add(anItem, anotherItem));
}
}
Generic<int> genInt = ...;
// and then instead of ...
genInt.DoSomething(1, 2);
// have to write:
genInt.DoSomething(1, 2, (a, b) => a + b);
Declare your own interface IAddable
. Then you can use it as a generic type parameter constraint, but obviously you can’t use int
as the parameter then. You would have to use a struct
of your own that contains just an int
and which implements IAddable
:
public interface IAddable<T> {
T Add(T other);
}
public struct Integer : IAddable<Integer> {
public int Value;
public Integer(int value) { Value = value; }
public Integer Add(Integer other) { return new Integer(Value + other.Value); }
}
// then instead of
Generic<int> blah = ...;
// have to write:
Generic<Integer> blah = ...;
dynamic
. Another possible workaround is to use dynamic
, but this is rather hacky and completely unsafe: it will let you pass in any type and call any method or operator, and only crash at runtime, not at compile-time.
In C# 4.0 is new keyword dynamic that allow you to perform this at runtime. In previous versions it was possible but too shady and tricky for me. But you can allways pass a delegate that will perform additions inside generic. Otherwise it is not possible because there is no ISummable, IAdditive and generally speaking no way to know is something is additive* at compilation time. If you wish some further comments I will add it later. BR.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With