C# 自定义编译器警告

C# 自定义编译器警告,c#,.net,vb.net,attributes,compiler-warnings,C#,.net,Vb.net,Attributes,Compiler Warnings,在.Net中使用ObsoleteAttribute时,它会向编译器发出警告,告诉您对象/方法/属性已过时,应使用其他内容。我目前正在从事一个项目,该项目需要对前雇员的代码进行大量重构。我想写一个自定义属性,我可以用它来标记方法或属性,这些方法或属性将生成编译器警告,给出我写的消息。像这样的 [MyAttribute(“此代码是sux,应该查看”)] 公共无效做任何事 { } 公共子行一切() 端接头 我想让它生成一个编译器警告,上面写着“这段代码是sux,应该查看”。我知道如何创建自定义属

在.Net中使用ObsoleteAttribute时,它会向编译器发出警告,告诉您对象/方法/属性已过时,应使用其他内容。我目前正在从事一个项目,该项目需要对前雇员的代码进行大量重构。我想写一个自定义属性,我可以用它来标记方法或属性,这些方法或属性将生成编译器警告,给出我写的消息。像这样的

[MyAttribute(“此代码是sux,应该查看”)]
公共无效做任何事
{
}

公共子行一切()
端接头

我想让它生成一个编译器警告,上面写着“这段代码是sux,应该查看”。我知道如何创建自定义属性,问题是如何使其在visual studio中生成编译器警告。

在某些编译器中,您可以使用“警告”发出警告:

#warning "Do not use ABC, which is deprecated. Use XYZ instead."
在Microsoft编译器中,通常可以使用消息pragma:

#pragma message ( "text" )

您提到了.Net,但没有说明是使用C/C++还是C#进行编程。如果你是用C#编程,你应该知道这一点。

我认为你做不到。据我所知,对ObsoleteAttribute的支持基本上是硬编码到C#编译器中的;你不能直接做类似的事情

您可以使用MSBuild任务(或生成后事件)对刚编译的程序集执行自定义工具。自定义工具将反映程序集中的所有类型/方法,并使用您的自定义属性,此时它可以打印到System.Console的默认或错误TextWriter。

这值得一试

您不能扩展Observe,因为它是最终的,但是您可以创建自己的属性,并将该类标记为Observe,如下所示:

[Obsolete("Should be refactored")]
public class MustRefactor: System.Attribute{}
//TODO:  This code sux and should be looked at
public class SuckyClass(){
  //TODO:  Do something really sucky here!
}
然后,当您使用“MustRefactor”属性标记方法时,将显示编译警告。它会生成一个编译时警告,但错误消息看起来很有趣,您应该亲自查看并选择。这与您想要实现的目标非常接近

更新: 它会生成一个警告(不是很好,但我认为没有更好的警告)。

public class User
{
    private String userName;

    [TooManyArgs] // Will show warning: Try removing some arguments
    public User(String userName)
    {
        this.userName = userName;   
    }

    public String UserName
    {
        get { return userName; }
    }
    [MustRefactor] // will show warning: Refactor is needed Here
    public override string ToString()
    {
        return "User: " + userName;
    }
}
[Obsolete("Refactor is needed Here")]
public class MustRefactor : System.Attribute
{

}
[Obsolete("Try removing some arguments")]
public class TooManyArgs : System.Attribute
{

}
从源代码看,它似乎没有做任何特殊的事情来生成编译器警告,所以我倾向于使用@,并说它是硬编码到编译器中的。有什么原因不想仅仅用来生成警告消息吗?

Update 这在Roslyn(Visual Studio 2015)中已成为可能。您可以使用来检查自定义属性


我认为这是不可能的。ObsoleteAttribute由编译器专门处理,并在C#标准中定义。究竟为什么过时的属性是不可接受的?在我看来,这正是它设计的目的,也正是实现你所需要的

还要注意的是,VisualStudio也会动态获取由ObsoleteAttribute生成的警告,这非常有用

不是说没有帮助,只是想知道为什么你不喜欢使用它

不幸的是,ObsoleteAttribute是密封的(可能部分是由于特殊处理),因此您不能从中对自己的属性进行子类化

根据C#标准:-

属性“过时”用于标记 类型和应该 不再使用

如果程序使用类型或成员 用过时的 属性,编译器发出 警告或错误。具体来说 如果没有错误,编译器将发出警告 参数,或者如果 参数已提供并具有 值为false。编译器发出一个 如果错误参数为,则为error 指定,并且其值为true


这不就是你的需求吗?。。。你不会做得比我想象的好。

我们现在正处于很多重构的中间,我们不能马上修复所有的东西。我们只需要使用#warning preproc命令,在这里我们需要返回并查看代码。它显示在编译器输出中。我不认为你可以把它放在一个方法中,但是你可以把它放在方法中,它仍然很容易找到

public void DoEverything() {
   #warning "This code sucks"
}
在VS 2008(+sp1)#清除解析和重建解决方案后,警告不会正确显示在错误列表中,没有所有警告。 只有在打开特定类文件后,错误列表中才会显示一些警告。 所以我不得不使用自定义属性:

[Obsolete("Mapping ToDo")]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property)]
public class MappingToDo : System.Attribute
{
    public string Comment = "";

    public MappingToDo(string comment)
    {
        Comment = comment;
    }

    public MappingToDo()
    {}
}
所以当我用它标记一些代码时

[MappingToDo("Some comment")]
public class MembershipHour : Entity
{
    // .....
}
它会产生如下警告:

Namespace.MappingToDo已过时: “映射待办事项”

我无法更改警告的文本,“某些注释”未显示在错误列表中。 但它将跳转到文件中的适当位置。
因此,如果您需要更改此类警告消息,请创建各种属性。

您试图做的是滥用属性。而是使用VisualStudio任务列表。您可以在代码中输入注释,如下所示:

[Obsolete("Should be refactored")]
public class MustRefactor: System.Attribute{}
//TODO:  This code sux and should be looked at
public class SuckyClass(){
  //TODO:  Do something really sucky here!
}
然后从菜单中打开视图/任务列表。任务列表有两个类别:用户任务和注释。切换到Comments,您将看到所有//待办事项:。双击TODO将跳转到代码中的注释


Al

有几条评论建议插入警告或pragma。 过时的作品在一个非常不同的方式!
将库L的函数标记为过时,即使调用方程序不在库L中,程序调用该函数时也会发出过时消息。警告仅在编译库L时才会发出消息。

以下是Roslyn实现,因此您可以创建自己的属性,动态发出警告或错误

我创建了一个名为
IdeMessage
的属性类型,该属性将生成警告:

[AttributeUsage(AttributeTargets.Method, AllowMultiple = true, Inherited = true)]
public class IDEMessageAttribute : Attribute
{
    public string Message;

    public IDEMessageAttribute(string message);
}
为此,您需要首先安装Roslyn SDK,并使用analyzer启动一个新的VSIX项目。我省略了一些不太相关的部分,比如信息,你可以想出办法。在您的分析器中,您可以这样做