可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
Resharper 5's new pattern matching seems very powerful, though it takes a bit of tinkering to work out how to use it.
For those who aren't familiar with this feature, it allows you to search for specific patterns within your code. Instances of such patterns may optionally be replaced with an alternative. In IntelliJ this was called structural search and replace. It's much more powerful than simple RegEx search/replace.
I'd like to collect a series of patterns that people are using so that I can learn how to use this feature better.
I propose that each answer include:
- a brief introduction of the rationale for the pattern
- an example of what it would match
- an optional example of a replacement
- the XML generated by exporting the pattern so that others can try it out too
回答1:
Matching a [Flags] enum bit
.NET 4 introduces the System.Enum.HasFlag
method which can tidy up your code.
Before:
(myValue & MyFlagsEnum.Foo) == MyFlagsEnum.Foo
After:
myValue.HasFlag(MyFlagsEnum.Foo)
XML:
<CustomPatterns>
<Pattern Severity="SUGGESTION">
<Comment>Can condense using 'Enum.HasFlag' method</Comment>
<ReplaceComment>Replace bit matching with 'Enum.HasFlag'</ReplaceComment>
<ReplacePattern>$myValue$.HasFlag($target$)</ReplacePattern>
<SearchPattern><![CDATA[($myValue$ & $target$) == $target$]]></SearchPattern>
<Params />
<Placeholders>
<ExpressionPlaceholder Name="myValue" ExpressionType="System.Enum" ExactType="False" />
<ExpressionPlaceholder Name="target" ExpressionType="System.Enum" ExactType="False" />
</Placeholders>
</Pattern>
</CustomPatterns>
回答2:
Remove if envelop around if body.
Example:
This code:
if (ok)
{
DoNextStep();
}
will be replaced by:
DoNextStep();
So only body of if remains.
The XML:
<Pattern Severity="HINT">
<Comment>if</Comment>
<ReplaceComment>Remove enclosing if</ReplaceComment>
<ReplacePattern>$body$</ReplacePattern>
<SearchPattern>if($condition$){$body$}</SearchPattern>
<Params />
<Placeholders>
<StatementPlaceholder Name="body" Minimal="-1" Maximal="-1" />
<ExpressionPlaceholder Name="condition" ExpressionType="System.Boolean" ExactType="True" />
</Placeholders>
</Pattern>
回答3:
JetBrains offer a Sample Pattern Catalog for Structural Search and Replace for download containing 17 patterns:
- 'try/finally' block can be converted to 'using' statement
- Method StringBuilder.Append can be converted to StringBuilder.AppendFormat
- Comparison with true is redundant
- Conditional statement is redundant
- Code is unreachable
- 'if' block is never executed
- Identical branches in a conditional statement
- Redundant compound assignment with |= operator
- Redundant compound assignment with &= operator
- Redundant compound assignment with |= operator (alternative case)
- Redundant compound assignment with &= operator (alternative case)
- Redundant initialization to false and condition block
- Redundant initialization to true and condition block
- Method Array.CreateInstance can be replaced with an array creation expression
- Method Array.CreateInstance can be replaced with a two-dimensional array creation expression
- Redundant usage of GetType() == typeof() with a value type
- Method OfType can be used for type-based filtering
回答4:
Restarting a Stopwatch
.NET 4 introduces the System.Diagnostics.Stopwatch.Restart()
method which can tidy up your code.
Before:
stopwatch.Reset();
stopwatch.Start();
After:
stopwatch.Restart();
XML:
<CustomPatterns>
<Pattern Severity="SUGGESTION">
<Comment>Use Restart method for System.Diagnostics.Stopwatch</Comment>
<ReplaceComment>Use Restart method for System.Diagnostics.Stopwatch</ReplaceComment>
<ReplacePattern>$stopwatch$.Restart();</ReplacePattern>
<SearchPattern><![CDATA[$stopwatch$.Reset();
$stopwatch$.Start();]]></SearchPattern>
<Params />
<Placeholders>
<ExpressionPlaceholder Name="stopwatch" ExpressionType="System.Diagnostics.Stopwatch" ExactType="True" />
</Placeholders>
</Pattern>
</CustomPatterns>
回答5:
This one's different. I discovered later in my project that mbunit asserts which compare property values to enums don't render nice messages when using the AssertEx.That
syntax.
So I created a pattern to find this:
AssertEx.That(() => myVariable.Status == MyEnum.Ok);
...and replace it with this:
Assert.AreEqual(MyEnum.Ok, myVariable.Status);
Here's the pattern:
<Pattern Severity="WARNING">
<Comment>AssertEx.That asserts for enum values don't give nice error msgs</Comment>
<ReplaceComment>Replace AssertEx.That asserts for enum values with trad Assert.AreEqual for better error msgs</ReplaceComment>
<ReplacePattern>Assert.AreEqual($enum$,$variable$.$property$)</ReplacePattern>
<SearchPattern><![CDATA[AssertEx.That(() => $variable$.$property$ == $enum$]]></SearchPattern>
<Params />
<Placeholders>
<ExpressionPlaceholder Name="enum" ExpressionType="System.Enum" ExactType="False" />
<IdentifierPlaceholder Name="variable" Type="" ExactType="False" RegEx="" CaseSensitive="True" />
<IdentifierPlaceholder Name="property" Type="" ExactType="False" RegEx="" CaseSensitive="True" />
</Placeholders>
回答6:
To 'as' cast.
Example:
This code:
string s = (string) o;
will be replaced by:
string s = o as string;
So now you have the 'as' cast instead of regular cast.
The XML:
<Pattern Severity="HINT">
<Comment>Cast</Comment>
<ReplaceComment>To 'as' cast</ReplaceComment>
<ReplacePattern>$exp$ as $type$</ReplacePattern>
<SearchPattern>($type$)$exp$</SearchPattern>
<Params />
<Placeholders>
<TypePlaceholder Name="type" Type="" ExactType="True" />
<ExpressionPlaceholder Name="exp" ExpressionType="" ExactType="True" />
</Placeholders>
</Pattern>
回答7:
Remove enclosing braces around a body.
Example:
This code:
foreach (int i in arr)
{
DoNextStep();
}
will be replaced (by Ctrl+L to remove foreach row and then run this pattern to remove braces) by:
DoNextStep();
So only body of braces remains after typing around two shortcuts.
The XML:
<Pattern Severity="HINT">
<Comment>Curly braces with body</Comment>
<ReplaceComment>Remove braces</ReplaceComment>
<ReplacePattern>$body$</ReplacePattern>
<SearchPattern>{$body$}</SearchPattern>
<Params />
<Placeholders>
<StatementPlaceholder Name="body" Minimal="-1" Maximal="-1" />
</Placeholders>
回答8:
To regular cast.
Example:
This code:
string s = o as string;
will be replaced by:
string s = (string) o;
So now you have the regular cast instead of 'as' cast.
The XML:
<Pattern Severity="HINT">
<Comment>Cast (as)</Comment>
<ReplaceComment>To regular cast</ReplaceComment>
<ReplacePattern>($type$)$exp$</ReplacePattern>
<SearchPattern>$exp$ as $type$</SearchPattern>
<Params />
<Placeholders>
<ExpressionPlaceholder Name="exp" ExpressionType="" ExactType="True" />
<TypePlaceholder Name="type" Type="" ExactType="True" />
</Placeholders>
</Pattern>
回答9:
For example, Microsoft recommends (and
Code Analysis/FxCop generates
appropriate warnings) if you are doing
a comparison between a string value
and an empty string, to use the
String.IsNullOrEmpty()
method.
http://david.gardiner.net.au/2010/02/resharper-5-structural-search-and.html