问题
I want to select code, e.g.
doSomething(myEnum.firstThing)
doSomethingElse(myEnum.firstThing)
evenMoreStuff(myEnum.firstThing)
and convert it to a function
GroupCommonStuf(myEnum.firstThing)
which would look like:
GroupCommonStuff(myEnum id)
{
doSomething(id)
doSomethingElse(id)
evenMoreStuff(id)
}
Preferably it would catch any code that is:
doSomething(myEnum.secondThing)
doSomethingElse(myEnum.secondThing)
evenMoreStuff(myEnum.secondThing)
and convert it to
GroupCommonStuf(myEnum.secondThing)
etc.
I have ReSharper installed. But the extract method in ReSharper seems to only extract the code block I select. It doesn't propagate it other "similar code", which I am sure Eclipse does for C++ and Java.
I assume I could also achieve this through regular expressions, but I am not regular expression enlightened yet. How can I do this?
回答1:
This is possible in three steps using three useful ReSharper tools:
- Extract To Method
- Introduce Parameter
- Search With Pattern
Possible alternatives without ReSharper are at the bottom
Select one offending code block, Extract To Method
(Ctrl + R, M)*** or right click → Refactor → Extract → Method)
Result:
GroupCommonStuf() { doSomething(myEnum.firstThing) doSomethingElse(myEnum.firstThing) evenMoreStuff(myEnum.firstThing) }
Select one "myEnum.firstThing" within the function, Introduce Parameter (Ctrl + R, P) or right click → Refactor → Introduce parameter
The wizard is pretty self explanatory :)
Result:
GroupCommonStuf(myEnum type) { doSomething(type) doSomethingElse(type) evenMoreStuff(type) }
ReSharper → Find → Search With Pattern (click replace tab)
OR Select an untouched offending code block, Right click* → Find Similar Code
Click Add PlaceHolder→ "Type" = Arguments → "Name"=enumeration
Type the following:
Result:
Using the above pattern script code blocks that match:
doSomething(myEnum.firstThing); doSomethingElse(myEnum.firstThing); evenMoreStuff(myEnum.firstThing);
will be replaced with
GroupCommonStuf(myEnum.firstThing)
The same for any variation of the enum :).
Some Explanation On What's Going On Here
In short, ReSharper is finding any arguments between ( ) and storing them in the variable "enumeration" (the name doesn't actually matter). Then inserting that string of arguments anywhere the variable appears in the replace block.
There are different placeholders that do different things and it's important to use the right one. The "type" placeholder even supports regular expressions which makes it incredibly powerful.
You could simply type $enumeration$ in this case because the default placeholder is "arguments". However I would advise getting in the habit of using "add placeholder" as it will be clearer when you do more complex patterns. It's important that you know it's not just "put strings here into variable".
To explain this better, consider this example, say you had the following code dotted around:
... = GetGraphic(Graphics.First).ShapeArray[index].ShapeColour
... = GetGraphic(Graphics.Second).ShapeArray[index].ShapeSize
... = GetGraphic(Graphics.First).ShapeArray[index].ShapeSize
And you had decided to replace all of these with code more akin to
... = GetShapeColour(Graphics.First, index);
... = GetShapeSize(Graphics.Second, index);
... = GetShapeSize(Graphics.First, index);
By using the correct place holders you can do this with one search and replace:
- $args$ (an argument placeholder) takes care of moving whatever the parameters is for you, in this case its just one, but it could be several.
- $variableOfArray$ (A type place holder, with regex set to
Shape*
) takes care of moving the ShapeColour, ShapeSize "variable type" names
If you had used "argument placeholder" for "variableOfArray" Resharper would have said it couldn't find any occurrences of that pattern because there was no such thing as GetGraphic( .. ).ShapeArray[index].( .. ).
Possible Work-arounds without ReSharper:
Extract To Method → Extract Method Refactoring
Introduce Parameter → "find replace" with/without Promote Variable To Parameter
Search With Pattern → This is clearly the hard one to me there are three options that I wouldn't particularly want to explore and my guess would be would generally require more time then it would to do the changes manually:
- VERY clever regular expression (this could be annoying within Visual Studio itself)
- Bash scripts with clever sed (slight improvement on just regexing within Visual Studio, but still hard)
- Writing your own parser???When all else fails...to the code!
来源:https://stackoverflow.com/questions/26674797/how-to-extract-common-similar-code-blocks-to-function-in-visual-studio-c-sharp