1

I know that interfaces cannot contain operators, but is there a way I can require / tell the compiler that the + and / operators will be implemented by a certain class?

I want to do something like this:

public class AutoAverage<T> where T:(overloads + and /)
{
  private List<T> history ;  // 10-20 values

  public T NextAvg( T newValue )
  {
    // implementation wants to push newValue
    // into history, then sum
    // values in history and return an average
  }
}
bobobobo
  • 64,917
  • 62
  • 258
  • 363
  • 2
    That's a frequently requested feature. Making it work would require significant work in the CLR, but it is certainly on their radar. It's a possible feature for hypothetical future versions, but no promises. – Eric Lippert Jun 13 '09 at 05:25

5 Answers5

3

Unfortunately, that isn't currently possible in C#.

mqp
  • 70,359
  • 14
  • 95
  • 123
3

In cases like this, sometimes I will pass lambdas to the constructor:

public class AutoAverage<T>
{
    public AutoAverage(Func<T, T, T> sum, Func<T, T, T> divide) { ...

And in usage:

var autoAverage = new AutoAverage((x, y) => x + y, (x, y) => x / y);
// ... use it ...

It's a bit ugly when you're doing binary operations like this (I've more often used it for single-argument functions, e.g. unit conversions), but it has the advantage of simplicity.

Whether that's a good solution in your case will depend, among other things, on how often you construct AutoAverage. If you only create it one or two places (for each T), then passing the lambdas wouldn't be that bad. If you construct it a whole bunch of places, the lambdas would be duplicated too much for comfort.

Joe White
  • 94,807
  • 60
  • 220
  • 330
2

You might be able to implement something close, using an interface as described in Marc Gravell's answer here: Solution for overloaded operator constraint in .NET generics

Community
  • 1
  • 1
Mitch Wheat
  • 295,962
  • 43
  • 465
  • 541
1

I'd try something like this:

interface ISumT<T>
{
  /// <summary>
  /// the sum method adds rhs to this and returns the result
  /// </summary>
  /// <remark>
  /// use a interface (i.e. ISumT)
  /// with a method (i.e. sum)
  /// because "where" doesn't support operators
  /// </remark>
  T sum(T rhs);
}

public class AutoAverage<T> where T : ISumT<T>
{
  public T NextAvg( T newValue )
  {
    // can assume that T implements the sum method
  }
}
ChrisW
  • 54,973
  • 13
  • 116
  • 224
  • ... it turns out that making classes that implement ISumT for all the primitives is actually kind of tedious! – bobobobo Jun 13 '09 at 13:36
1

MiscUtil has generic aggregate functions (Sum, Average, etc) built in, using .NET 3.5 to provide generic operator support at runtime.

Additionally, C# 4.0 makes this possible via dynamic (which supports operators), but the above approach is usually faster (less indirection).

Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900