C# 根据API使用情况动态创建编译器错误?

C# 根据API使用情况动态创建编译器错误?,c#,java,compiler-construction,compiler-errors,static-analysis,C#,Java,Compiler Construction,Compiler Errors,Static Analysis,我不知道如何搜索这个问题的答案,但我想知道在Java、C#、Scala等编译语言中是否有办法。。。在API使用不正确的情况下强制编译器出错 假设您正在使用某种类型的API,并且您知道在调用其他方法Y之前需要调用特定的设置方法X,那么是否可以进行设置,以使编译器能够捕获错误并避免在运行时这样做 它对于强制执行某些代码标准或修复损坏的API非常有用。不知道这是否可能。特定函数的使用是在编译器操作之外的另一个层次上。。。因此我不认为编译器应该做这样的事情 另一方面:编译器通常集成到IDE中。。。为什么

我不知道如何搜索这个问题的答案,但我想知道在Java、C#、Scala等编译语言中是否有办法。。。在API使用不正确的情况下强制编译器出错

假设您正在使用某种类型的API,并且您知道在调用其他方法Y之前需要调用特定的设置方法X,那么是否可以进行设置,以使编译器能够捕获错误并避免在运行时这样做


它对于强制执行某些代码标准或修复损坏的API非常有用。不知道这是否可能。

特定函数的使用是在编译器操作之外的另一个层次上。。。因此我不认为编译器应该做这样的事情

另一方面:编译器通常集成到IDE中。。。为什么不把它也放到IDE模块中呢。。。大多数IDE允许预编译操作


您可以编写某种检查工具(基于CodeDOM或类似工具)来测试特定函数的使用情况,并基于该检查结果,在质量标准不匹配时中止编译器运行…

通常,在大多数静态语言中,您不能创建任意自定义编译时错误。在C和C++中有一些例外(比如<代码> <错误> /COD>指令,但是即使预处理器严格地在主编译之前,也不会有帮助)。 但是,您可以利用专门设计用于在编译时捕获错误的语言功能:

类型系统是您的朋友。 要求按特定顺序调用方法对API使用者来说是不友好的,而且在高级语言中是一种代码味道

一个简单的解决方案是公开一个方法,该方法以正确的顺序执行这两个操作。更一般地说(例如,如果不需要调用第二个方法),让第二个方法调用顶部的第一个方法。但您可能希望调用由API使用者控制

在这种情况下,重构代码,这样就不可能在不创建类型错误的情况下以错误的顺序调用方法。例如,假设您正在编写一个正则表达式库,其中在匹配之前必须编译正则表达式。在Scala中,重构:

class Regex(pattern : String) {
    private[this] var compiled : Option[CompiledData] = None
    def compile() {
        // do stuff
        this.compiled = ...
    }
    def search(s : String) : MatchResult = compiled match {
        case Some(c) => ... // match the string
        case None => throw new IllegalStateException("must compile regex first")

    }
}

由于
search
方法现在仅在
CompiledRegex
上可用,并且
CompiledRegex
是通过调用
Regex.compile
获得的,因此在编译Regex使该操作生效之前,不可能调用
search

此设置还可以帮助API使用者,因为如果用户需要类型为
MatchResult
的对象,并且已经键入了
newregex(“[abc123]*”)
,一个好的IDE可以自动完成或建议所需的方法
。compile
;这在原始设置中是不可能的

(在本例中,它也不再需要可变状态,这在Scala中通常是避免的。)

静态断言 作为替代解决方案,一些语言(我认为是D和C++11,尽管不是您列出的语言)支持静态断言。

像或let write这样的工具可以在分析时发出(,或)。例如,以下CQLinq代码规则强制规定,如果一个方法正在调用
MethodA()
,它必须调用
MethodB()


对于预处理,您可以做的事情非常有限。很可能只有运行时错误才能处理这些问题。@AlvinWong:哦,但是有一个静态功能可以验证某些需求……我同意这是正确的方法,但有时没有包装器是不可能的。。。。因此,我想在编译器中内置一些检查。
class Regex(pattern : String) {
    def compile : CompiledRegex = {
        // do stuff
        CompiledRegex(...)
    }
}
class CompiledRegex(c : CompiledData) {
    def search(s : String) : MatchResult = {
        ... // match the string
    }
}
warnif count > 0 
from m in Application.Methods where
 m.IsUsing("MyNamespace.MyClass.MyMethodA()") &&
!m.IsUsing("MyNamespace.MyClass.MyMethodB()")
select m