代码之家  ›  专栏  ›  技术社区  ›  Lasse V. Karlsen

有关缺少IDisposable实现的未挂起cql查询

  •  4
  • Lasse V. Karlsen  · 技术社区  · 16 年前

    我意识到这个问题要查找的查询不足以发现IDisposable实现中的每个小问题,但是每个早期警告都很重要,所以我将尽我所能。

    我想知道是否有人提出了一个关于ndepend的CQL查询,该查询将列出所有没有实现IDisposable的类,但有一个或多个字段可以实现。一个类最终可能会出现在这个查询的结果列表中,要么是通过一个bug(即某人忘记检查IDisposable实现的字段类型),要么是通过代码进化(即,某个字段中使用的类稍后会被附加到IDisposable上,而不会更新所有用法)。

    查找所有未实现IDisposable的类的简单查询是:

    SELECT TYPES WHERE !Implement "System.IDisposable"
    

    但是,这当然不会检查类 应该 实现上述规则的IDisposable。

    有人有这样的疑问吗?我仍在和CQL打交道,所以这部分内容让我无法理解。

    1 回复  |  直到 13 年前
        1
  •  6
  •   Patrick from NDepend team    13 年前

    由于cqlinq(Linq上的代码规则)的功能,现在可以匹配应该实现IDisposable的类型。实际上,现在提供了两个相关的默认规则,您可以轻松地编写自己的相关规则:


    // <Name>Types with disposable instance fields must be disposable</Name>
    warnif count > 0
    
    let iDisposable = ThirdParty.Types.WithFullName("System.IDisposable").FirstOrDefault() 
    where iDisposable != null // iDisposable can be null if the code base doesn't use at all System.IDisposable
    
    from t in Application.Types where 
       !t.Implement(iDisposable) && 
       !t.IsGeneratedByCompiler 
    
    let instanceFieldsDisposable = 
        t.InstanceFields.Where(f => f.FieldType != null &&
                                    f.FieldType.Implement(iDisposable))
    
    where instanceFieldsDisposable.Count() > 0
    select new { t, instanceFieldsDisposable }
    

    // <Name>Disposable types with unmanaged resources should declare finalizer</Name>
    // warnif count > 0
    let iDisposable = ThirdParty.Types.WithFullName("System.IDisposable").SingleOrDefault()
    where iDisposable != null // iDisposable can be null if the code base deosn't use at all System.IDisposable
    
    let disposableTypes = Application.Types.ThatImplement(iDisposable)
    let unmanagedResourcesFields = disposableTypes.ChildFields().Where(f => 
       !f.IsStatic && 
        f.FieldType != null && 
        f.FieldType.FullName.EqualsAny("System.IntPtr","System.UIntPtr","System.Runtime.InteropServices.HandleRef")).ToHashSet()
    let disposableTypesWithUnmanagedResource = unmanagedResourcesFields.ParentTypes()
    
    from t in disposableTypesWithUnmanagedResource
    where !t.HasFinalizer
    let unmanagedResourcesTypeFields = unmanagedResourcesFields.Intersect(t.InstanceFields)
    select new { t, unmanagedResourcesTypeFields }
    
    推荐文章