Sonar在处理c# 5异步方法时似乎会计算无效的LCOM4

本文关键字:计算 无效 LCOM4 处理 异步方法 Sonar | 更新日期: 2023-09-27 18:17:53

当类使用异步方法时,Sonar似乎不会为类计算正确的LCOM4值。

我在一个类中有三个async方法,都访问/操作类中的相同字段,但LCOM4指示值为3,并向我显示三个方法。

实际上,async方法经过编译器转换后,这些方法不共享相同的字段,因为方法被编译器转换为设置状态机,并且它是另一个方法中的状态机,该方法实际上保存了原始方法的代码。

无论如何,是否有人确认Sonar在处理c# 5 async方法时不能正确计算LCOM4 ?是否有任何已经存在的解决方案,或者有一个计划?

编辑

下面是一些代码示例:下面是一个非常简单的类的非异步版本:

public class LComNonAsync
{
    public bool State { get; private set; }
    public void Enable()
    {
        this.State = true;
    }
    public void Disable()
    {
        this.State = false;
    }
}

下面是async版本:

public class LComAsync
{
    public bool State { get; private set; }
    public async Task EnableAsync()
    {
        await Task.Yield();
        this.State = true;
    }
    public async Task DisableAsync()
    {
        await Task.Yield();
        this.State = false;
    }
}

一旦运行Sonar,如果我看一下这两个类的LCOM4,下面是我可以看到的:

LComNonAsync :

方法缺乏内聚性:1

1 State (property)

系统。空白禁用()

系统。空白使()

And for LComAsync:

方法的衔接不足:2

1 System.Threading.Tasks.Task EnableAsync()

2 System.Threading.Tasks.Task disable ()

我在async方法中放置了await语句,但我确信即使没有等待,问题也会存在。方法被标记为async的唯一事实是触发方法的async编译器转换。编译器转换后,从IL的角度来看,如前所述,公共方法体将被状态机的设置/启动状态机所取代,方法的实际原始代码将放置在该状态机的MoveNext方法中。因此,"State"属性不再在原来的公共方法中被引用,并触发LCOM4 "violation"。

事实上,这不是我在Sonar和c# 5 async/await中遇到的唯一问题。我们已经开始了一个非常依赖c# 5的async/await结构的大型项目,并且不得不将我们的项目集成到Sonar中,因为公司希望我们这样做(几天前刚刚发现Sonar,它太棒了……尽管c# 5在某些方面没有得到正确的支持……无论如何)。我面临的另一个问题是静态代码分析。我们不得不禁用Gendarme,因为它会对某些规则产生很多误报,这是由于c# 5的异步方法转换,而对其他规则则是由于任务的使用……所以我们决定依赖FxCop,但FxCop10在c# Sonar生态系统中提供,但它也不考虑。net Framework 4.5/c# 5,所以我们将使用FxCop11,它正确支持c# 5,但它还没有作为一个独立版本可用-还吗?-这似乎是一个痛苦的…将它从visual studio 2012中取出,并将其独立放在分析机上…无论如何,代码分析是一个完全不同的关注点,与LCOM4问题完全无关,但这只是为了分享;)

Sonar在处理c# 5异步方法时似乎会计算无效的LCOM4

在撰写本文时,由于缺乏答案和我的测试,我认为Sonar在计算LCOM4时不能正确地使用c# 5 async/await结构。