【问题标题】:Generics in C# binary operator overloadingC# 二元运算符重载中的泛型
【发布时间】:2021-01-25 06:51:15
【问题描述】:

考虑两个泛型类

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

是否有某种方法可以重载 + 运算符,从而允许我编写以下内容,以便在结果中正确捕获类型,即 r 的类型为 Result&lt;int,string&gt;

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&lt;T&gt;,例如两个Value&lt;int&gt;,但是当类型不同时呢?

查看以前有关 C# 运算符重载的问题,似乎没有一个回答这个特定问题。这个可能是最接近的:Overloading operator for generics C#

这样做的动机是,如果Result&lt;T1, T2&gt; 类有一个将委托作为参数的方法,那么在编译时知道T1T2 的具体类型就可以从调用该方法时的 lambda 表达式。

【问题讨论】:

  • 所以您希望为Value&lt;T&gt;Value&lt;U&gt;TU 的任何两种类型定义一个运算符+
  • @Sweeper 没错。

标签: c# operator-overloading


【解决方案1】:

对于要在任意两个Value&lt;T&gt;Value&lt;U&gt; 上定义的运算符+,其中TU 是任何类型,运算符需要是通用的。使用一些虚构的语法,它看起来像:

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,它适用于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

【讨论】:

  • 我怀疑是这样的。这有点令人失望,因为似乎没有任何理由可以像这样禁止运算符重载中的泛型。
猜你喜欢
  • 2014-02-23
  • 1970-01-01
  • 2015-05-23
  • 2012-03-24
  • 1970-01-01
  • 2010-10-19
  • 2017-04-28
  • 2011-10-06
  • 2011-05-01
相关资源
最近更新 更多