当我意识到可能无法区分使用 <
的表达式时,我正在努力创建自己的静态类型语言。运算符和类或方法的类型参数。
这样做的主要原因是,像 C# 一样,类在使用之前不必全部进行前向声明,因此当标识符在 <
之后被解析时。 ,它可以是像 valueA < valueB
这样的表达式或者它可能是一个类型参数,如 valueA<valueB>
.
所以我想,也许如果有一个结束 >
,然后它可以被解析为一个类型参数,但后来我想起我希望我的语言有运算符重载,所以像 valueA < valueB > (valueC)
这样的表达式可能是完全有效的。
我决定尝试其他语言,我发现 C# 与我试图创建的语言最相似,我可能已经破坏了它。
表达式 foo < bar > (2)
在下面的代码中应该是一个完全有效的表达式,因为类重载 <
和 >
运营商。
据我所知,表达式应该被解析为 (foo < bar) > (2)
,但我收到一个错误,指出 "The variable 'foo' cannot be used with type arguments."
为了证明这个表达式应该是有效的,我翻转了 <
和 >
标志使表情看起来像 foo > bar < (2)
,并且该程序的编译和打印出的内容完全符合您的预期,MainClass+baz
.
在这个特定的例子中,编译器可能会解决这个问题,因为它知道 foo
是一个变量,它可以假设 <
表示一个表达式,但如果 foo 是另一个类的静态成员,则无法区分 <
表达式和类型参数。
using System;
class MainClass {
public static void Main (string[] args) {
baz foo = new baz();
baz bar = new baz();
// perfectly valid expression, results in error: The variable `foo' cannot be used with type arguments
Console.WriteLine(foo < bar > (2));
}
class baz {
public static baz operator<(baz l, baz r) {
return l;
}
public static baz operator>(baz l, baz r) {
return l;
}
public static baz operator<(baz l, int r) {
return l;
}
public static baz operator>(baz l, int r) {
return l;
}
}
public String toString() {
return "baz";
}
}
我的问题是,应该如何在 C# 编译器和其他语言中处理这个问题?
我看到几个选项:
也许对此有某种标准,但我认为接受这只是疏忽,我们至少应该选择选项 1。
最佳答案
foo
是局部变量,但您尝试将其用作类类型名称...
因此,它根本不是一个完全有效的表达式。
你不能写:
baz foo = new baz();
baz bar = new baz();
Console.WriteLine(foo<bar>(2));
但是你可以写:
var instance = baz<int>(2);
如果你有:
class baz<T>
{
}
在这里,您尝试使用泛型类型参数 int 创建类 baz 的实例,而不使用
new
关键字或者它可能是一个误写的强制转换,但编译器不知道。当您定义类时
baz<T>
这就是所谓的 开放泛型 .当你实例化
baz<int>
这就是所谓的封闭构造泛型 .您编写下面的代码应该是一个完全有效的表达式,因为该类具有重载的 < 和 > 运算符...
但是编译器无法解释
val1 < val2 > (val3)
如 val1 < val2 && val2 > (val3)
与数学规则一样,或作为 (val1 < val2) > (val3)
就像你写的一样,因为运算符 <>()
优先于 <
和 >
.编译器认为您尝试使用
baz of T
,所以编译器输出错误,因为编译器无法在两种情况之间选择,在<>()
之间和 <
下一个 >
.所以编译器将其解释为
Type<Type>(parameter)
没有别的。
关于c# - Mono C# 编译器将完全有效的表达式解释为错误的类型参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58652280/