C# 二元运算符重载中的泛型
Generics in C# binary operator overloading
考虑两个通用的 classes
class Result<T1, T2> {}
class Value<T> {}
是否有某种重载 +
运算符的方法,允许我以在结果中正确捕获类型的方式编写以下内容,即 r
具有类型 Result<int,string>
?
Value<int> a;
Value<string> b;
var r = a + b;
我可以这样写:
class Value<T> {
public static Result<T,T> operator+(Value<T> a, Value<T> b) { ... }
}
哪个适用于任何一对 Value<T>
,例如两个 Value<int>
,但是当类型不同时呢?
查看之前有关 C# 运算符重载的问题,其中 none 似乎回答了这个特定问题。这一个可能是最接近的:
尝试这样做的动机是,如果 Result<T1, T2>
class 有一个将委托作为参数的方法,知道特定类型 T1
和 T2
在编译时可以在调用该方法时从 lambda 表达式中省略类型。
为了在任意两个Value<T>
和Value<U>
上定义运算符+
,其中T
和U
是任意类型,运算符需要是通用的。使用一些虚构的语法,它看起来像:
class Value<T> {
public static Result<T,U> operator+<U>(Value<T> a, Value<U> b) {
// create a Result<T, U>
}
}
但是,自定义操作符的syntax非常严格,完全不像方法声明的那样:
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 ';'
| ';'
;
虽然它们看起来很像方法声明,但它们的语法以非常不同的方式指定,并且不允许泛型参数。
此外,使用这个假设的泛型运算符需要 type inference, which is applied when invoking a method。这不会在运算符解析期间发生。
作为解决方法,您可以声明一个 Plus
方法:
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
考虑两个通用的 classes
class Result<T1, T2> {}
class Value<T> {}
是否有某种重载 +
运算符的方法,允许我以在结果中正确捕获类型的方式编写以下内容,即 r
具有类型 Result<int,string>
?
Value<int> a;
Value<string> b;
var r = a + b;
我可以这样写:
class Value<T> {
public static Result<T,T> operator+(Value<T> a, Value<T> b) { ... }
}
哪个适用于任何一对 Value<T>
,例如两个 Value<int>
,但是当类型不同时呢?
查看之前有关 C# 运算符重载的问题,其中 none 似乎回答了这个特定问题。这一个可能是最接近的:
尝试这样做的动机是,如果 Result<T1, T2>
class 有一个将委托作为参数的方法,知道特定类型 T1
和 T2
在编译时可以在调用该方法时从 lambda 表达式中省略类型。
为了在任意两个Value<T>
和Value<U>
上定义运算符+
,其中T
和U
是任意类型,运算符需要是通用的。使用一些虚构的语法,它看起来像:
class Value<T> {
public static Result<T,U> operator+<U>(Value<T> a, Value<U> b) {
// create a Result<T, U>
}
}
但是,自定义操作符的syntax非常严格,完全不像方法声明的那样:
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 ';'
| ';'
;
虽然它们看起来很像方法声明,但它们的语法以非常不同的方式指定,并且不允许泛型参数。
此外,使用这个假设的泛型运算符需要 type inference, which is applied when invoking a method。这不会在运算符解析期间发生。
作为解决方法,您可以声明一个 Plus
方法:
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