在C#中是否可以创建新的运算符?

69

我知道你可以重载一个已有的操作符,但我想知道是否可能创建一个新的操作符。以下是我的场景:

我希望实现这个功能:

var x = (y < z) ? y : z;

要与此等效:

var x = y <? z;

换言之,我想创建自己的<?运算符。


16
不正确。正如其他人指出的那样,F# 和 C++ 都有这个功能。CoffeeScript 为 JavaScript 语言习惯提供了几个新操作符,可以将其视为允许自定义操作符。但最后一个有点棘手,因为技术上你会扩展语言。 - Justin Morgan
在Scala中,它将是 implicit class <?(y: Int) { def <?(z: Int) = y min z } -- 这是一个隐式类,用于向 Int 添加一个方法,然后是方法本身。_这个_特定的方法不起作用,因为 <? 是一个xml-start关键字。 - Daniel C. Sobral
1
即使可能,我仍然认为这不是一个好主意。它比一个方法(例如Min(y, z))难以阅读得多。 - Thomas Levesque
2
@userSteve 这已经被提议用于 C# 8 - null 合并赋值 - phuzi
1
@AminM,实际上有成千上万种编程语言比C#更好地处理运算符。 - Ramsey
显示剩余10条评论
7个回答

47

不,这是不可能的。您需要创建一个方法来实现。


30

不可以,但是在C#中你可以重载一些现有的运算符

在其他一些语言中,比如F#,你可以使用:

let (<?) = min

5
实际上,应该是最小值,而不是最大值 ;) - Thomas Levesque

20

如其他答案所述,您无法创建新的运算符 - 至少,不会在不更改编译器内置的词法分析器和语法分析器的情况下。基本上,编译器被构建为识别单个字符(如<?)或一对字符(如>><=)作为运算符,并进行特殊处理;它知道i<5是表达式而不是变量名,例如。将运算符识别为运算符是与决定运算符实际执行的过程分开的过程,并且与编译器紧密集成 - 这就是您可以自定义后者但无法自定义前者的原因。

对于具有开源编译器的语言(如GCC),你理论上可以修改编译器以识别新的运算符。但这并不容易,而且此外,每个人都需要使用您的自定义编译器才能使用您的代码。


为了明确起见,在C++中人们使用宏来做这样的事情?我不懂C ++,只是问一下。 - Camilo Martin
或者只使用操作符作为中缀方法的语言,如Scala或F#。 - Electric Coffee

10

我很惊讶没有人提到"运算顺序"。

当编译器评估一个表达式时,必须考虑以正确的顺序执行操作,这样在表达式中相同的“级别”上,乘法始终在加法之前执行,例如(1+2*3)=(2*3+1)

当您重载运算符时,可以更改运算符的功能,但不能更改编译器评估它的顺序。如果您创建了新的运算符,则无法告诉编译器与其他运算符相比评估它的顺序。因此,如果您写 x <? 2 + 5,是先执行x <? 2然后加5还是先执行加法然后再做x <? 7无从得知。


如果这个功能在某个时候被添加到C#中,你可能(因为它还不是一个“东西”)只需使用属性,如[OrderOfOperations.Dot],告诉编译器使其具有与点操作(*,/,**)相同的优先级。 - GoldenretriverYT

7

不仅你不能这样做,而且你为什么想这样做呢?

我不确定您的 y 和 z 是什么类型,但如果它们是数字类型,您可以尝试使用:

var x = Math.Min(y, z);

尽管个人而言,我仍然更喜欢:
var x = (y < z) ? y : z;

但我有点成为“?:狂热者”。

好的代码不仅紧凑高效,而且易读。即使您是唯一阅读它的人,某天您也会回来看到那个<?运算符并想知道它到底是做什么的。


2
不过,如果像这个问题所问的那样,在另一种语言中已经是一个已知的特性,那么就可以。http://stackoverflow.com/questions/523403/can-i-define-a-perl-like-binding-operator-in-c - Camilo Martin
1
同样的话也适用于任何运算符重载。 - JNF
9
我不同意。我认为运算符重载在许多情况下是有意义的。例如,如果将两个类型的实例相加是有意义的,你可能希望重载+运算符而不是创建一个.Add()方法。直观地说,某人看到“+”符号时就会理解这个操作符正在对两个东西进行算术相加。如果重载的效果正是这样,那么它很容易被理解。 - Paul Hooper
1
我想使用 ====,这样我的整个开发团队都知道我们正在为该特定对象使用覆盖的测试。就这样,但是,是的...我只是想避免在if语句中使用方法...只是闲逛。 - Piotr Kula

6
不行,但你可以创建扩展方法来代替此操作。
y.MethodName(z)

7
如果不够小,那么就执行(1) :) - Oleksandr Zolotarov
我这里有 true.Xor(false)... :( - SparK

-4

你可以尝试重载其他运算符,如%+,以充当<?运算符。

会很有趣的。


2
这不是他问题的答案。 - Patrick Hofman
不,这不是一个答案,但它某种程度上说明了它可能演变成多么荒谬。 - Marcelo Scofano Diniz

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接