Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/laravel/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Properties 如何使用NDepend查找哪些属性getter具有副作用?_Properties_Immutability_Ndepend_Cql_Cqlinq - Fatal编程技术网

Properties 如何使用NDepend查找哪些属性getter具有副作用?

Properties 如何使用NDepend查找哪些属性getter具有副作用?,properties,immutability,ndepend,cql,cqlinq,Properties,Immutability,Ndepend,Cql,Cqlinq,使用VisualStudio的一个常见问题是属性获取程序的神秘调用。如果这些都有副作用(最常见的形式是If(foo==null)foo=new foo();return foo;),那么调试器局部变量和监视窗口调用属性(甚至没有达到任何断点)这一事实可能会在调试时导致意外的效果 有一个简单的解决方案:只需用属性标记属性 [DebuggerBrowsable(DebuggerBrowsableState.Never)] 那么,如何才能在大型代码库中找到可能有副作用的getter呢

使用VisualStudio的一个常见问题是属性获取程序的神秘调用。如果这些都有副作用(最常见的形式是
If(foo==null)foo=new foo();return foo;
),那么调试器局部变量和监视窗口调用属性(甚至没有达到任何断点)这一事实可能会在调试时导致意外的效果

有一个简单的解决方案:只需用属性标记属性

        [DebuggerBrowsable(DebuggerBrowsableState.Never)]
那么,如何才能在大型代码库中找到可能有副作用的getter呢

是这类事情的首选工具:使用其CQL语言,我可以找到所有属性,例如,直接更改其包含实例的状态:

         SELECT METHODS FROM ASSEMBLIES "FOO" 
         WHERE IsPropertyGetter AND ChangesObjectState 

这只会找到那些直接更改字段的getter:我如何才能找到那些间接更改字段的getter,例如通过调用
Initialize()
方法?

Joel,这是由于(CQLinq)。下面是一个CQLinq查询,用于检测属性获取程序的深度可变性。对于每个引发可变性的getter,代码查询显示分配的字段集

// Restrict the iteration only on property getters
// that are changing states or that call a method that changes state
let propertyGetters = Application.Methods.Where(m => m.IsPropertyGetter)

let methodsThatChangeState = 
  Application.Methods.Where(m => m.ChangesObjectState || m.ChangesTypeState)

from m in propertyGetters.DepthOfIsUsingAny(methodsThatChangeState).DefinitionDomain
          .Union(propertyGetters.Intersect(methodsThatChangeState))

// Find all methods called directly or indirectly by the property getter
let methodsCalledIndirectly = 
        m.MethodsCalled.FillIterative(
           methods => methods.SelectMany(m1 => m1.MethodsCalled))
        .DefinitionDomain
        .Union(m.ToEnumerable())

// Gather all field assigned that are not generated by the compiler
let fieldsAssigned = methodsCalledIndirectly
                     .SelectMany(m1 => m1.FieldsAssigned)
                     .Where(f => !f.IsGeneratedByCompiler)

where fieldsAssigned.Any()
orderby fieldsAssigned.Count() descending 
select new { m, fieldsAssigned }
这个查询很复杂,主要是因为我对它进行了优化,首先只保留本身正在更改状态的getter,或者直接或间接调用正在更改状态的方法(call to)的getter

然后,对于每个getter,我们构建直接或间接调用的所有方法集(由于调用),并收集所有该方法分配的所有字段

具体而言,查询结果如下所示:


谢谢你,帕特里克。顺便问一下,有没有可能使用CQL来确定一个方法是否可能通过接口使用?Joel,现在几乎所有的事情都可以通过CQLinq实现(请参阅我的新答案),如果您有其他需要,请问一个新问题。