Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
187 views
in Technique[技术] by (71.8m points)

Generics in C# binary operator overloading

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.

question from:https://stackoverflow.com/questions/65880133/generics-in-c-sharp-binary-operator-overloading

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...