9

我正在使用Visual Studio 2013.我正在修改其他人留下的一些可怕的代码,它使用几乎独占的全局变量,并试图清理它,以便我可以正确封装每个函数并且不会在什么传入(或从中返回)。如何在C#中查找当前范围外定义的变量?

是否有任何方法可以轻松检查整个项目的变量,这些变量是在它们被使用的范围之外定义的?

我知道我可以点击一个变量,并且SHIFT+F12会找到我用于该单个变量的用法,但是我想在整个项目中找到所有这些用法,因为问题真的很糟糕......它不是只有一两个全局变量,我在说几十个。试图了解这个程序的流程和它的状态足以让你喝得很重!

+0

会不会只是成员变量?除非你也关心突变参数? –

+3

R#可能会对您有所帮助。不知道是否有内置功能。 @MarkBrackett,OP正在讨论不需要成员变量的成员变量,因为它们只用于一种方法。 – bzlm

+0

@bzlm,差不多。它们是全局变量,用于在全球范围内通过几十个函数中的状态。所以我试图将变量本地化到需要的每个函数中,并使用参数,以便程序及其数据的状态更容易理解,以便干净地封装并取消所有全局变量。 – eidylon

回答

1

应该有一种工具,它已经以树形格式做这件事,但没有任何通常的嫌疑人似乎没有Find Usages舞蹈。

所以,这里试图通过查找所有成员变量来使用Reflection API,然后检查方法并确定它们是否触及它们。

你现在基本上是在查看IL,所以除非你想自己确定解析规则,否则你会想使用像塞西尔这样的反汇编程序。我正在使用deprecated single file implementation cause it's easy。像Roslyn分析器或JustDecompile插件就像另一条路线,但我没有经验。

肯定会出现边缘情况,如果你正在寻找一个完整的依赖关系图,代码将变得更加复杂 - 但对于快速和脏的分析,它至少应该给你一个概述。

所以,基本上你使用反射加上IL读者作出从变量地图 - >方法(你可以去太多的其他方式,但是这可能不值钱):

var variables = typeof(SmallBallOfMud).GetFields(BindingFlags.Instance | BindingFlags.NonPublic); 
var methods = typeof(SmallBallOfMud).GetMethods(BindingFlags.Instance | BindingFlags.NonPublic); 

var d = new Dictionary<string, List<string>>(); 
foreach (var v in variables) d.Add(v.Name, new List<string>()); 

// this particular disassembler chokes on externally implemented methods 
foreach (var m in methods.Where(m => (m.MethodImplementationFlags | MethodImplAttributes.IL) == 0)) { 
    var instructions = MethodBodyReader.GetInstructions(m); 

    foreach (var i in instructions) { 
     // we'll only check for direct field access here 
     var f = i.Operand as FieldInfo; 
     if (f == null) continue;    
     d[f.Name].Add(m.Name); 
    } 
} 

我们的结果将是如:

state1: Method1 (1), Method2 (1) 
state2: Method2 (2) 
state3: Method1 (1), Method2 (2) 

这被读作“状态3”被“方法1”使用一次,“方法2”使用两次。

+0

要点:代码:https://gist.github.com/mbrackett/335e18071bbb17f08ce2 –