0

Consider two generic classes

class Result<T1, T2> {}
class Value<T> {}

Is there some way of overloading the + operator that would allow me to write the following in such a way that the types are properly captured in the result, i.e. r has the type Result<int,string>?

Value<int> a;
Value<string> b;
var r = a + b;

I can write this:

class Value<T> {
   public static Result<T,T> operator+(Value<T> a, Value<T> b) { ... }
}

Which will work for any pair of Value<T>'s, such as two Value<int>'s, but what about when the types differ?

Looking at previous questions about C# operator overloading, none of them seem to answer this specific question. This one is perhaps the closest: Overloading operator for generics C#

The motivation behind trying to do this is that if the Result<T1, T2> class has a method that takes a delegate as an argument, knowing the specific types T1 and T2 at compile time makes it possible to omit types from the lambda expression when calling that method.

2
  • So you want an operator + to be defined for Value<T> and Value<U> for any two types T and U? Commented Jan 25, 2021 at 6:58
  • @Sweeper That's correct. Commented Jan 25, 2021 at 7:09

1 Answer 1

2

For the operator + to be defined on any two Value<T> and Value<U>, where T and U are any types, the operator needs to be generic. Using some made-up syntax, it would look something like:

class Value<T> {
    public static Result<T,U> operator+<U>(Value<T> a, Value<U> b) { 
        // create a Result<T, U>
    }
}

However, the syntax of user-defined operators is very strict, and is nowhere like that of method declarations:

operator_declaration
    : attributes? operator_modifier+ operator_declarator operator_body
    ;
operator_declarator
    : unary_operator_declarator
    | binary_operator_declarator
    | conversion_operator_declarator
    ;
binary_operator_declarator
    : type 'operator' overloadable_binary_operator '(' type identifier ',' type identifier ')'
    ;

overloadable_binary_operator
    : '+'   | '-'   | '*'   | '/'   | '%'   | '&'   | '|'   | '^'   | '<<'
    | right_shift | '=='  | '!='  | '>'   | '<'   | '>='  | '<='
    ;
operator_body
    : block
    | '=>' expression ';'
    | ';'
    ;

Though they may look a lot like method declarations, their syntax is specified in a very different way, and do not allow generic parameters.

Furthermore, using this hypothetical generic operator would require type inference, which is applied when invoking a method. This does not happen during operator resolution.

As a workaround, you can declare a Plus method:

class Value<T> {
    public Result<T,U> Plus<U>(Value<U> other) { 
        // create a Result<T, U>
    }
}

// You'd be doing a.Plus(b), rather than "a + b"
// You still get the type inference you wanted
Sign up to request clarification or add additional context in comments.

1 Comment

I suspected that was the case. It's a bit disappointing, because there doesn't seem to be any reason why generics in operator overloading should be disallowed like this.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.