Delen via


Resharper tip #1: Push code into a method / Pull code out of a method

Resharper is a great tool, but many times that operation that I want to perform isn’t possible with a single refactoring; you need multiple refactorings to get the result that you want. I did a search and could find these anywhere, so I thought I’d share them with you.

If you know where more of these things are described and/or you know a better way of doing what I describe, please let me know.

Push code into a method

Consider the following code:

    1: static void Main(string[] args)
    2: {
    3:     DateTime start = DateTime.Now;
    4:  
    5:  
    6:     DateTime oneDayEarlier = start - TimeSpan.FromDays(1);
    7:     string startString = start.ToShortDateString();
    8:  
    9:     Process(oneDayEarlier, startString);
   10:  
   11: }
   12:  
   13: private static void Process(DateTime oneDayEarlier, string startString)
   14: {
   15:     Console.WriteLine(oneDayEarlier);
   16:     Console.WriteLine(startString);
   17: }
 

Looking at the code in Main(), there are a couple of variables that are passed into the Process() method. A little examination shows that things would be cleaner they were in the Process method, but there’s no “move code into method” refactoring, so I’ll have to synthesize it out of the refactorings that I have. I start by renaming the Process() method to Process2(). Use whatever name you want here:

    1: class Program
    2: {
    3:     static void Main(string[] args)
    4:     {
    5:         DateTime start = DateTime.Now;
    6:  
    7:  
    8:         DateTime oneDayEarlier = start - TimeSpan.FromDays(1);
    9:         string startString = start.ToShortDateString();
   10:  
   11:         Process2(oneDayEarlier, startString);
   12:  
   13:     }
   14:  
   15:     private static void Process2(DateTime oneDayEarlier, string startString)
   16:     {
   17:         Console.WriteLine(oneDayEarlier);
   18:         Console.WriteLine(startString);
   19:     }
   20: }

Next, select the lines that I want to include into the method plus the method call itself, and do an Extract Method refactoring to create a new Process() method:

    1: static void Main(string[] args)
    2: {
    3:     DateTime start = DateTime.Now;
    4:  
    5:  
    6:     Process(start);
    7: }
    8:  
    9: private static void Process(DateTime start)
   10: {
   11:     DateTime oneDayEarlier = start - TimeSpan.FromDays(1);
   12:     string startString = start.ToShortDateString();
   13:  
   14:     Process2(oneDayEarlier, startString);
   15: }
   16:  
   17: private static void Process2(DateTime oneDayEarlier, string startString)
   18: {
   19:     Console.WriteLine(oneDayEarlier);
   20:     Console.WriteLine(startString);
   21: }

Finally, inline the Process2() method:

    1: class Program
    2: {
    3:     static void Main(string[] args)
    4:     {
    5:         DateTime start = DateTime.Now;
    6:  
    7:  
    8:         Process(start);
    9:     }
   10:  
   11:     private static void Process(DateTime start)
   12:     {
   13:         DateTime oneDayEarlier = start - TimeSpan.FromDays(1);
   14:         string startString = start.ToShortDateString();
   15:  
   16:         Console.WriteLine(oneDayEarlier);
   17:         Console.WriteLine(startString);
   18:     }
   19: }

Three quick refactorings got me to where I wanted, and it’s about 15 seconds of work if you use the predefined keys.

Pull Code Out of a Method

Sometimes, I have some code that I want to pull out of a method. Consider the following:

    1: class Program
    2: {
    3:     static void Main(string[] args)
    4:     {
    5:         int n = 15;
    6:  
    7:         WriteInformation("Information: ", n);
    8:     }
    9:  
   10:     private static void WriteInformation(string information, int n)
   11:     {
   12:         File.WriteAllText("information.txt", information + n);
   13:     }
   14: }

I have a few options here. We can pull “information.txt” out easily by selecting it and using Introduce Parameter:

    1: class Program
    2: {
    3:     static void Main(string[] args)
    4:     {
    5:         int n = 15;
    6:  
    7:         WriteInformation("Information: ", n, "information.txt");
    8:     }
    9:  
   10:     private static void WriteInformation(string information, int n, string filename)
   11:     {
   12:         File.WriteAllText(filename, information + n);
   13:     }
   14: }

I could use that same approach to pull out “information + n”, but I’m going to do it an alternate way that works well if I have a chunk of code. First, I introduce a variable:

    1: class Program
    2: {
    3:     static void Main(string[] args)
    4:     {
    5:         int n = 15;
    6:  
    7:         WriteInformation("Information: ", n, "information.txt");
    8:     }
    9:  
   10:     private static void WriteInformation(string information, int n, string filename)
   11:     {
   12:         string contents = information + n;
   13:         File.WriteAllText(filename, contents);
   14:     }
   15: }

I rename the method:

    1: class Program
    2: {
    3:     static void Main(string[] args)
    4:     {
    5:         int n = 15;
    6:  
    7:         WriteInformation2("Information: ", n, "information.txt");
    8:     }
    9:  
   10:     private static void WriteInformation2(string information, int n, string filename)
   11:     {
   12:         string contents = information + n;
   13:         File.WriteAllText(filename, contents);
   14:     }
   15: }

And I now extract the code that I want to remain in the method to a new method:

    1: class Program
    2: {
    3:     static void Main(string[] args)
    4:     {
    5:         int n = 15;
    6:  
    7:         WriteInformation2("Information: ", n, "information.txt");
    8:     }
    9:  
   10:     private static void WriteInformation2(string information, int n, string filename)
   11:     {
   12:         string contents = information + n;
   13:         WriteInformation(filename, contents);
   14:     }
   15:  
   16:     private static void WriteInformation(string filename, string contents)
   17:     {
   18:         File.WriteAllText(filename, contents);
   19:     }
   20: }

And, finally, I inline the original method:

    1: class Program
    2: {
    3:     static void Main(string[] args)
    4:     {
    5:         int n = 15;
    6:  
    7:         string contents = "Information: " + n;
    8:         WriteInformation("information.txt", contents);
    9:     }
   10:  
   11:     private static void WriteInformation(string filename, string contents)
   12:     {
   13:         File.WriteAllText(filename, contents);
   14:     }
   15: }

Comments

  • Anonymous
    October 13, 2015
    Would be nice if you could also add the information about the shourtcuts!

  • Anonymous
    October 13, 2015
    Good idea. Shortcuts I used; CTRL-R M    Extract method CTRL-R V     Introduce variable CTRL-R P     Introduce parameter CTRL-R I      Inline method CTRL-R R     Rename

  • Anonymous
    October 13, 2015
    Hi, for the first case, it is simplier to just inline Process, then select lines you need and extract method with same name "Process". No rename stage in workflow. For the second problem it is also the case: inline method, extract variable, extract method.

  • Anonymous
    October 13, 2015
    And IDEA keymap version: Ctrl+Alt+M    Extract method Ctrl+Alt+V     Introduce variable Ctrl+Alt+P     Introduce parameter Ctrl+Alt+N     Inline method F2                   Rename

  • Anonymous
    November 05, 2015
    Thanks for this.  Would love to see you continue on with Resharper Tip #2, ...