Define a generic that implements the + operator
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 useint
as the parameter then. You would have to use astruct
of your own that contains just anint
and which implementsIAddable
: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 usedynamic
, 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.
Is there a generic constraint I could use for the + operator?
There are no such devices in C#. A few options are available, though:
- in C# 4.0 and .NET 4.0 (or above), use
dynamic
, which supports+
but offers no compile time checking - in .NET 3.5 (or above), MiscUtil offers an
Operator
class which makes operators available as methods - again, without any compile-time checking
So either:
return (dynamic)left.Evaluate(context) + (dynamic)right.Evaluate(context);
or
return Operator.Add(left.Evaluate(context), right.Evaluate(context));
operator overloading with generics
The problem is the compiler cannot know if +
operator can be applied to T
. Unfortunately, there is no way to constraint T
to be a numeric type in C#.
However, you might be able to workaround this using the dynamic runtime:
public class Complex<T> where T : struct
{
public T _a, _b;
public Complex(T i, T j)
{
_a = i;
_b = j;
}
public static Complex<T> operator +(Complex<T> i, Complex<T> j)
{
return new Complex<T>(Sum(i._a, j._a), Sum(i._b, j._b));
}
private static T Sum(T a, T b)
{
return (dynamic)a + (dynamic)b;
}
}
Can't operator == be applied to generic types in C#?
"...by default == behaves as described above for both predefined and user-defined reference types."
Type T is not necessarily a reference type, so the compiler can't make that assumption.
However, this will compile because it is more explicit:
bool Compare<T>(T x, T y) where T : class
{
return x == y;
}
Follow up to additional question, "But, in case I'm using a reference type, would the the == operator use the predefined reference comparison, or would it use the overloaded version of the operator if a type defined one?"
I would have thought that == on the Generics would use the overloaded version, but the following test demonstrates otherwise. Interesting... I'd love to know why! If someone knows please share.
namespace TestProject
{
class Program
{
static void Main(string[] args)
{
Test a = new Test();
Test b = new Test();
Console.WriteLine("Inline:");
bool x = a == b;
Console.WriteLine("Generic:");
Compare<Test>(a, b);
}
static bool Compare<T>(T x, T y) where T : class
{
return x == y;
}
}
class Test
{
public static bool operator ==(Test a, Test b)
{
Console.WriteLine("Overloaded == called");
return a.Equals(b);
}
public static bool operator !=(Test a, Test b)
{
Console.WriteLine("Overloaded != called");
return a.Equals(b);
}
}
}
Output
Inline:
Overloaded == called
Generic:
Press any key to continue . . .
Follow Up 2
I do want to point out that changing my compare method to
static bool Compare<T>(T x, T y) where T : Test
{
return x == y;
}
causes the overloaded == operator to be called. I guess without specifying the type (as a where), the compiler can't infer that it should use the overloaded operator... though I'd think that it would have enough information to make that decision even without specifying the type.
How to ensure type in a generic implements some operators in Dart?
I think the best you can do is just assume that the elements have these methods and leave the type parameter unbounded. That will get rid of the warnings, though it's probably a bit unsatisfying when you want the type system to help you out.
Union types would help, so here's the bug you can star: http://dartbug.com/4938
C# Generic Operators
No, you can't declare generic operators in C#.
Operators and inheritance don't really mix well.
If you want Foo + Foo to return a Foo and Bar + Bar to return a Bar, you will need to define one operator on each class. But, since operators are static, you won't get the benefits of polymorphism because which operator to call will be decided at compile-time:
Foo x = new Bar();
Foo y = new Bar();
var z = x + y; // calls Foo.operator+;
Related Topics
How to Simulate a Mouse Click at a Certain Position on the Screen
Change Custom Attribute's Parameter at Runtime
C# - How to Make Two Forms Reference Each Other
How to Create "Embedded" SQL 2008 Database File If It Doesn't Exist
How to Connect and Use a SQLite Database from C#
Define a Generic That Implements the + Operator
Truncate String on Whole Words in .Net C#
How to Know the Selected Checkboxes from Within the Httppost Create Action Method
Some Help Understanding "Yield"
Httpcontext.Current Is Null When Unit Test
How to Check If a Number Is Positive or Negative in C#
How to Get the Text of a Messagebox When It Has an Icon
MVC HTML.Beginform Different Url Schema
Change Flow of Messages in Microsoft Bot Framework