How to extract common/similar code blocks to function in Visual Studio C#

蓝咒 提交于 2019-12-19 03:44:10

问题


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


  1. Select one offending code block, Extract To Method

    (Ctrl + R, M)*** or right clickRefactorExtractMethod)

    Result:

    GroupCommonStuf()
    {
        doSomething(myEnum.firstThing)
        doSomethingElse(myEnum.firstThing)
        evenMoreStuff(myEnum.firstThing)
    
    }
    
  2. Select one "myEnum.firstThing" within the function, Introduce Parameter (Ctrl + R, P) or right clickRefactorIntroduce parameter

    The wizard is pretty self explanatory :)

    Result:

    GroupCommonStuf(myEnum type)
    {
        doSomething(type)
        doSomethingElse(type)
        evenMoreStuff(type)
    }
    
  3. ReSharper → FindSearch With Pattern (click replace tab)

    OR Select an untouched offending code block, Right click* → Find Similar Code

  4. Click Add PlaceHolder→ "Type" = Arguments → "Name"=enumeration

  5. 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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!