我想计算TCC指标:
紧密级别凝聚力(TCC) 衡量人数的比例 方法对直接连接 类NDC(C)和类中的可见方法 最大可能方法的数量 两对之间的连接 NP(C)类的可见方法。二 可见方法是直接的 连接,如果他们正在访问 该类的相同实例变量。 n是可见方法的数量 导致:
NP(C) = (n(n-1))/2
和
TCC(C) = NDC(C) / NP(C)
所以我编写了一个方法来解析我要检查的类中的所有方法。此方法存储该类中的所有方法以及它们在字典中使用的字段,如下所示:
Dictionary<MethodDefinition, IList<FieldReference>> references = new Dictionary<MethodDefinition, IList<FieldReference>>();
现在,如何遍历此词典以检查上述情况?如果我理解正确的话,我必须找到使用同一组字段的这两对方法?那我怎么能以最好的方式做到这一点呢?我想我必须遍历字典并查看IList是否包含相同的集合? (甚至不是以相同的顺序)?
任何想法?
我的代码如下,但它无法正常工作:
class TCC
{
public static int calculate(TypeDefinition type)
{
int count = 0;
Dictionary<MethodDefinition, HashSet<FieldReference>> references = new Dictionary<MethodDefinition, HashSet<FieldReference>>();
foreach (MethodDefinition method in type.Methods)
{
if (method.IsPublic)
{
references.Add(method, calculateReferences(method));
}
}
for (int i = 0; i < references.Keys.Count; i++)
{
HashSet<FieldReference> list = new HashSet<FieldReference>();
references.TryGetValue(references.Keys.ElementAt(i), out list);
if (isPair(references, list)) {
count++;
}
}
if (count > 0)
{
count = count / 2;
}
return count;
}
private static bool isPair(Dictionary<MethodDefinition, HashSet<FieldReference>> references, HashSet<FieldReference> compare)
{
for (int j = 0; j < references.Keys.Count; j++)
{
HashSet<FieldReference> compareList = new HashSet<FieldReference>();
references.TryGetValue(references.Keys.ElementAt(j), out compareList);
for (int i = 0; i < compare.Count; i++)
{
if (containsAllElements(compareList, compare)) {
return true;
}
}
}
return false;
}
private static bool containsAllElements(HashSet<FieldReference> compareList, HashSet<FieldReference> compare)
{
for (int i = 0; i < compare.Count; i++)
{
if (!compareList.Contains(compare.ElementAt(i)))
{
return false;
}
}
return true;
}
private static HashSet<FieldReference> calculateReferences(MethodDefinition method)
{
HashSet<FieldReference> references = new HashSet<FieldReference>();
foreach (Instruction instruction in method.Body.Instructions)
{
if (instruction.OpCode == OpCodes.Ldfld)
{
FieldReference field = instruction.Operand as FieldReference;
if (field != null)
{
references.Add(field);
}
}
}
return references;
}
}
答案 0 :(得分:2)
好吧,如果你不介意另外一本字典,我们可以用一把大锤子打这个东西 简单地说,如果我们想象一个字典,其中ordered_set(字段引用)是键,而我们保留每个键的值列表....不用说这不是最聪明的方法,但它是快速,简单,并使用您已熟悉的数据结构。
EG:
hashset< hashset < FieldReference >, Ilist< methods >> Favorite_delicatessen
Build ReferenceSet for method
Look up ReferenceSet in Favorite_Delicatessen
If there:
Add method to method list
Else:
Add Referenceset,method pair
因此你的方法列表是共享相同状态签名的方法列表,如果你让我用一个术语。
答案 1 :(得分:1)
您可以使用ContainsValue检查重复项吗?根据您描述的内容,如果值相同,则只显示重复项。
答案 2 :(得分:1)
由于您没有告诉我们如何判断两个FieldReference
是否重复,我将使用默认值。
LINQ版本:
int duplicated = references.SelectMany( p => p.Value )
.GroupBy(x => x)
.Where(g => g.Count() > 1)
.Count();
答案 3 :(得分:1)
如何获取字符,其中键是重复项,并且值是原始字典中包含副本的键列表:
var dupes = references
.SelectMany(k => k.Value)
.GroupBy(v => v)
.Where(g => g.Count() > 1)
.ToDictionary(i => i.Key, i => references
.Where(f => f.Value.Contains(i.Key))
.Select(o => o.Key));