我将一个(C#)结构转换为一个类,需要经历所有类型的使用,以确保前一个隐式副本和现在引用行为没有不良影响。
有没有办法找到使用/涉及此特定类型的所有引用?
我在类型上尝试Find all References
,并获得明确说明类型名称的所有位置,这是一个良好的开端。
但是,我没有获得返回和修改此类型实例的位置。特别是我使用var
将返回值分配给隐含类型变量的行,或者对先前定义的变量的所有赋值。
我可以使用任何功能或技巧吗?我想,这种结构到类转换的特殊情况经常发生。也许您对如何找到所有可能的问题有一些建议?
答案 0 :(得分:5)
您可以手动重命名该类...每个错误都是使用它的地方。但我认为Visual Studio将在发生一定数量的错误后停止。
您可以将[Obsolete]
标记为类,其所有属性及其所有方法。然后每次使用它们时都会收到警告。
请注意,[Obsolete]
“技巧”有一些限制:
[Obsolete]
public class MyClass
{
}
public static void Test1(MyClass test2) // This line has a warning
{
var y = test2; // ***This line doesn't have a warning***
MyClass z = test2; // This line has a warning
}
所以它与Find all References
...
另一种解决方案,基于Visual Studio的FxCop /代码分析:
的说明程序集的默认命名空间(您可以在属性中设置)必须为MyCustomFxCopRules
。平台目标是x86。
using Microsoft.FxCop.Sdk;
namespace MyCustomFxCopRules
{
public class StructAssignmentFinder : BaseIntrospectionRule
{
public StructAssignmentFinder()
: base("StructAssignmentFinder", "MyCustomFxCopRules.RuleMetadata", typeof(StructAssignmentFinder).Assembly)
{
var ms = new MyStruct();
var tt = ms;
}
public override TargetVisibilities TargetVisibility
{
get
{
return TargetVisibilities.All;
}
}
public override ProblemCollection Check(ModuleNode module)
{
Visit(module);
return Problems;
}
public override void VisitAssignmentStatement(AssignmentStatement assignment)
{
// You could even use FullName
if ((assignment.Source != null && assignment.Source.Type != null && assignment.Source.Type.Name.Name == "MyStruct") ||
(assignment.Target != null && assignment.Target.Type != null && assignment.Target.Type.Name.Name == "MyStruct"))
{
Problem problem = new Problem(GetNamedResolution("Struct", assignment.Target.Type.Name.Name), assignment);
Problems.Add(problem);
}
base.VisitAssignmentStatement(assignment);
}
public override void VisitConstruct(Construct construct)
{
Method targetMethod = (Method)((MemberBinding)construct.Constructor).BoundMember;
if (targetMethod.Parameters.Any(x => x.Type.Name.Name == "MyStruct"))
{
Problem problem = new Problem(GetNamedResolution("ParameterType", "MyStruct", targetMethod.Name.Name), construct);
Problems.Add(problem);
}
base.VisitConstruct(construct);
}
public override void VisitMethodCall(MethodCall call)
{
Method targetMethod = (Method)((MemberBinding)call.Callee).BoundMember;
if (targetMethod.ReturnType.Name.Name == "MyStruct")
{
Problem problem = new Problem(GetNamedResolution("ReturnType", targetMethod.ReturnType.Name.Name, targetMethod.Name.Name), call);
Problems.Add(problem);
}
if (targetMethod.Parameters.Any(x => x.Type.Name.Name == "MyStruct"))
{
Problem problem = new Problem(GetNamedResolution("ParameterType", "MyStruct", targetMethod.Name.Name), call);
Problems.Add(problem);
}
base.VisitMethodCall(call);
}
RuleMetadata.xml
(必须是嵌入式资源)
<?xml version="1.0" encoding="utf-8" ?>
<Rules FriendlyName="Rules about Structs">
<Rule TypeName="StructAssignmentRule" Category="MyRules" CheckId="CR1000">
<Name>Struct Assignment Finder</Name>
<Description>Struct Assignment Finder</Description>
<Url></Url>
<Resolution Name="Struct">There is an assignment of struct '{0}'.</Resolution>
<Resolution Name="ReturnType">'{0}' is the return type for a call to '{1}'.</Resolution>
<Resolution Name="ParameterType">'{0}' is a parameter type for a call to '{1}'.</Resolution>
<Email></Email>
<MessageLevel Certainty="100">Warning</MessageLevel>
<FixCategories>NonBreaking</FixCategories>
<Owner></Owner>
</Rule>
</Rules>
基于此,很容易为其他角落案例添加其他规则,我肯定会忘记: - )
我正在使用的测试文件:
public struct MyStruct
{
}
class Test
{
public Test()
{
var ms = new MyStruct();
var ms2 = ms;
ms3 = ms;
ms = ms3;
ms4 = ms;
ms = ms4;
ms4 = ms4;
new MyObject(default(MyStruct));
}
public MyStruct ms3;
public MyStruct ms4 { get; set; }
}
public class MyObject
{
public MyObject(MyStruct par1)
{
}
}
请注意,调试规则很棘手......使用FxCopCmd.exe
进行调试非常容易,但在Visual Studio直接调用时无法调试(我认为,不确定)。
答案 1 :(得分:2)
答案和评论使我找到了一个令人满意的解决方案,可能会帮助其他人,所以我想我会发布它。
问题不是找到所有用途,而只是问题&#34;一,即对公众成员的写访问。而不是像this answer中所建议的那样找到对成员的所有引用,我只想找到写访问权。因此,我使用了this answer中指示的重写策略,并使所有成员都只写,因此编译器只会抱怨危险的写访问。
这反过来将struct / class转换为注释中概述的不可变类型。这使得设计更加清洁。我只是重写了编译器抱怨的所有写访问,以尊重不可变的设计。此后,结构和类很大程度上可以交换,转换很容易。
只有对结构的默认构造函数的调用才会出现问题,该结构在类中不再存在。但我不再需要它们,因为在课堂上我可以简单地将这些案例设置为null
。
答案 2 :(得分:1)
您可以在每个类非私人成员上执行“查找所有引用”,一次一个。它会向这些成员显示每次读写。
答案 3 :(得分:0)
如果安装了Visual Studio Web Essentials Extension,则非常简单。 查看下面的截图。单击红色突出显示的链接,您可以看到特定类型的所有引用。