Refactoring catalog
Every refactoring RefactorMCP aims to support, described as behaviour and specified by fixtures: a compilable before, the operation, and the exact after.
No refactoring matches.
Primitives 100
Single, behaviour-preserving transformations.
Add Delegating Member
Adds to a class a member that forwards to the member of the same name of one of its fields, or of its base class. Replace Inheritance with Delegation uses it to give a class, while it still derives from its base class, its own members for the inherited ones other code uses, so the class can later stop deriving without its callers noticing.
Add Default Value to Parameter
Makes a parameter optional by giving it a default value, and optionally drops the arguments that pass that same value.
Change Accessibility
Changes the declared accessibility of a type or member, refusing when that would break a reference, an override or an interface implementation, or quietly change what a call binds to.
Change Base Type
Sets, replaces or removes the base class of a class. Extract Superclass and Replace Inheritance with Delegation use it to move a class under a new parent or off an old one.
Change Return Type
Changes the declared return type of a method, and of every override, interface member and implementation that must match it, when the method's body and every caller stay valid.
Change Signature
Adds, removes and reorders the parameters of a method or constructor, and updates every call in the solution to match. Overrides, overridden methods, interface members and their implementations change together, since they must keep the same parameters.
Change Type
Changes the declared type of a local, parameter, field, property or method return value, typically to a base type or interface its uses need ("use base type where possible"). Introduce Interface for Dependency uses it after Extract Interface.
Cleanup Usings
Removes the using directives in a file that nothing in it needs.
Consolidate Duplicate Conditional Fragments
Moves statements that every branch of a conditional starts or ends with out of the conditional, so they are written once.
Convert Anonymous Type to Class
Replaces an anonymous type with a named class that behaves the same, and constructs that class wherever the containing member creates the anonymous type.
Convert Auto-Property to Property with Backing Field
Gives an auto-property an explicit private field and accessors that read and write it, so the accessors can later gain behaviour. The reverse of Convert to Auto-Property.
Convert Class to Record
Turns a class whose state is fixed by its constructor into a record: a positional record where the constructor only assigns its parameters to get-only properties, otherwise the same members with class changed to record.
Convert String Concatenation to Interpolation
Turns a chain of + string concatenations into one interpolated string: "Hello, " + name + "!" becomes $"Hello, {name}!".
Convert Extension Method to Static Method
The reverse of Convert to Extension Method: an extension method becomes an ordinary static method, and every extension-style call becomes a static call.
Convert For to Foreach
Turns an index loop that only reads each element of a collection in turn into a foreach over the collection: for (int i = 0; i < items.Count; i++) with items[i] in the body becomes foreach (T item in items) with item. The reverse of Convert Foreach to For.
Convert Foreach to For
Turns a foreach over an indexable collection into an index loop that reads each element into the loop's variable: foreach (var item in items) becomes for (int i = 0; i < items.Count; i++) with var item = items[i]; as the first statement of the body. The reverse of Convert For to Foreach.
Convert Foreach to LINQ
Turns a foreach loop that builds a list, a total, a count or a flag from a sequence into a LINQ query in method syntax. The reverse of Convert LINQ to Foreach.
Convert If Chain to Switch Statement
Turns an if / else if chain that compares one value with constants or patterns into a switch statement on that value.
Convert Lambda to Method Group
Replaces a lambda that only passes its parameters on to a method, such as n => Format(n), with the method group Format. The reverse of Convert Method Group to Lambda.
Convert LINQ to Foreach
Turns a LINQ query of Where and Select ending in ToList, Sum, Count or Any into a foreach loop that builds the same result. The reverse of Convert Foreach to LINQ.
Convert Local Function to Method
Moves a local function out of its member to a private method of the containing type. Variables it captures become parameters. The reverse of Convert Method to Local Function.
Convert Local to Field
Promotes a local variable to a private field of the containing type. The declaration becomes an assignment to the field and every use refers to the field. A step of Replace Method with Method Object.
Convert Method Group to Lambda
Replaces a method group used as a delegate, such as Format, with a lambda calling it, such as number => Format(number). The reverse of Convert Lambda to Method Group.
Convert Method to Local Function
Moves a private method used by only one member into that member as a local function. The reverse of Convert Local Function to Method.
Convert Method to Property
Turns a parameterless method that returns a value, such as GetTotal(), into a get-only property, and every call into a property read.
Convert Primary Constructor to Constructor
Replaces a class or struct's primary constructor with an explicit constructor, storing each captured parameter in a private field.
Convert Property to Methods
Replaces a property with a Get method and, when it has a setter, a Set method, and turns every read and write into a call.
Convert Record to Class
Turns a record into a class that behaves the same: a positional record's constructor, properties and Deconstruct are written out, and the value equality, ToString and == operators the compiler generated for the record are generated as source.
Convert Setter to Init-Only
Replaces a property's set accessor with an init accessor, so the property can only be set while the object is being created.
Convert Switch Expression to Switch Statement
Turns a switch expression that is the whole value of a return, an assignment or a local's initialiser into a switch statement.
Convert Switch Statement to Switch Expression
Turns a switch statement whose every section produces a value into a switch expression that is returned or assigned.
Convert to Auto-Property
Replaces a property whose accessors only read and write a private field with an auto-property, and removes the field.
Convert to Block Body
Replaces an expression body with a block holding the equivalent statement. The reverse of Convert to Expression Body.
Convert to Block Namespace
Turns a file's namespace Shop; declaration into a namespace Shop { ... } block around everything after it, indenting that code a level. The reverse of Convert to File-Scoped Namespace.
Convert to Expression Body
Replaces a block body holding a single statement with an expression body. The reverse of Convert to Block Body.
Convert to Extension Method
Makes a method callable as an extension method on the type of its first parameter.
Convert to File-Scoped Namespace
Turns a file's namespace Shop { ... } block into a namespace Shop; declaration, taking a level of indentation off the code inside.
Convert to Primary Constructor
Replaces a constructor that only hands its parameters to fields and properties with a C# 12 primary constructor. Private fields that merely hold a parameter are removed and their uses read the parameter directly; other members are initialized from it.
Convert Tuple to Named Type
Replaces a tuple in a method's signature, its return type or one of its parameters, with a named positional record, and updates the method's body and its callers to construct and read it.
Create Type
Creates an empty class, interface, record or struct, either in a new file or at the end of an existing one. Composite recipes such as Extract Class and Extract Superclass start with it, so it takes no target, only arguments.
Encapsulate Collection
Stops callers changing a type's list behind its back: the list is exposed as a read-only view, and the type gains Add and Remove methods for the changes it allows.
Encapsulate Field
Makes a field private behind a property that reads and writes it, and points code outside the declaring type at the property.
Extract Interface
Declares some or all of a class's public members in a new interface, in a new file, and makes the class implement it. Introduce Interface for Dependency uses it before changing the type of a field or parameter to the interface.
Extract Local Variable
Also known as Introduce Variable. Declares a local holding a selected expression just before the statement that contains it, and uses the local in place of the expression. The reverse of Inline Local Variable.
Extract Method
Moves a run of statements, or a single expression, out of a method body into a new private method, and replaces them with a call to it.
Initialize Field from Constructor Parameter
Assigns a field that nothing uses yet from a constructor parameter, at the end of the constructor. Nothing reads the field, so the assignment changes nothing the code does; it prepares the field for a later step, such as Replace Expression with Field in Constructor Injection's recipe.
Inline Constant
Replaces every use of a constant field, across the solution, with its value and removes the constant.
Inline Field
Replaces every read of a field that is only ever assigned by its initialiser with that initialiser, across the solution, and removes the field.
Inline Local Variable
Replaces every use of a local with the expression it was initialised with, and removes the declaration. The reverse of Extract Local Variable.
Inline Method
Replaces every call of a method with the method's body, across the solution, and deletes the method. The reverse of Extract Method. A read-only property whose getter computes its value is inlined the same way at every read.
Inline Parameter
When every call passes the same constant for a parameter, removes the parameter and writes the constant where the body used it.
Inline Type Alias
Writes the type an alias names in place of every use of the alias and removes the alias's using directive. The reverse of Introduce Type Alias.
Introduce Constant
Replaces a selected literal or constant expression with a named constant of the containing type, and optionally every other occurrence of the same value in that type. The catalog's answer to a magic number.
Introduce Field
Stores the value of a selected expression in a new field of the containing type and uses the field in its place. A second form adds a field of a named type to a type, which composite recipes such as Extract Class use to hold the object that members move to.
Introduce Generic Type Parameter
Replaces a concrete type used in a class or method with a new type parameter, constrained as the uses need, and passes the old type wherever the class or method is used, so every existing use means what it did.
Introduce Parameter
Turns an expression in a method body into a new parameter. The expression is replaced by the parameter, and every call passes the expression instead, computed from that call's own arguments.
Introduce Type Alias
Declares a using alias for a type written in a file, such as using StockIndex = System.Collections.Generic.Dictionary<string, System.Collections.Generic.List<int>>;, and writes the alias wherever the file names that type.
Introduce Using Declaration
Turns a using statement whose block runs to the end of its enclosing block into a C# 8 using declaration followed by the block's statements:
Invert Boolean
Inverts the meaning of a bool field, property, method or local: renames it, gives it the negation of every value it was given, and negates every use, so that IsEnabled can become IsDisabled without changing behaviour.
Invert If
Negates the condition of an if statement and swaps its branches.
Join Declaration and Assignment
Joins a local declaration that has no initializer with the first assignment to the local: T x; followed by x = e; becomes T x = e;. The reverse of Split Declaration and Assignment.
Make Field Readonly
Adds readonly to a field that is only assigned while an object is being constructed, so the compiler enforces what the code already does.
Make Method Async
Makes a method that blocks on tasks async: it awaits them instead and returns a task. Its callers get the task, and block on it where they used to get the value, so only the method itself changes shape. Convert to Async repeats this on each caller up to a boundary.
Make Method Instance
The reverse of Make Method Static with pass: instance: a static method that takes an instance of its own type becomes an instance method on that parameter.
Make Method Static
Turns an instance method into a static method of the same class, and updates every call across the solution to pass what the method used to take from the instance.
Make Type Partial
Adds the partial modifier to a class, struct, record or interface, so its members can be spread over several declarations.
Merge Nested If
Joins an if whose only statement is another if into a single if on both conditions: if (a) { if (b) { S } } becomes if (a && b) { S }.
Merge Partial Declarations
Moves the members of every part of a partial type into one of its declarations, deleting the parts and any file they leave empty.
Merge Sibling Ifs
Joins an if with the if after it when both have the same body, into one if on both conditions: if (a) { S } else if (b) { S } and if (a) { return; } if (b) { return; } become if (a || b) { S } and if (a || b) { return; }. The counterpart of Merge Nested If, which joins with &&.
Move Field
Moves a field to another type. An instance field moves onto the type of another field or property of its class (the "via") and is reached through it, or into the class that holds its class (into), whose uses went through that holder; a static field or constant moves to a named type.
Move Instance Method
Moves an instance method onto the type of one of its class's fields or properties, or of one of its own parameters. That field, property or parameter (the "via") becomes this in the method's new home. Or, with into, moves it the other way: into the class that holds its class in a field or property (the "holder"), which it then reaches the rest of its old class through.
Move Member to Another Partial File
Moves a member of a partial type into the part of that type declared in another file, or into a new file holding a new part.
Move Property
Moves a property to another type. An instance property moves onto the type of a field or property of its class (the "via") and is reached through it, or into the class that holds its class (into), whose uses went through that holder; a static property moves to a named type.
Move Static Method
Moves a static method to another type, named by the caller, creating that type as a static class when it does not exist.
Move Type to File
Moves a top-level type out of a file that declares several types into a new file of its own, named after the type, in the same folder and project.
Move Type to Namespace
Changes the namespace a top-level type is declared in, leaving it in its file, and keeps every reference to it compiling across the solution.
Pull Up Constructor Body
Moves the statements at the start of a subclass constructor that only set up the base class into a base constructor, and makes the subclass constructor chain to it.
Pull Up Field
Moves a field from a class into its base class. The other subclasses that declare the same field lose their copy, since they now inherit it.
Pull Up Method
Moves a method from a class into its base class, or declares it abstract in the base class and makes the subclasses' versions override it.
Push Down Field
Moves a field from a class into the direct subclasses that need it: those whose code uses it, or whose callers reach it through a reference of the subclass's type. When nothing uses the field, every direct subclass gets a copy, so the declaration is never lost.
Push Down Method
Moves a method from a class into the direct subclasses that need it: those whose code calls it, or whose callers reach it through a reference of the subclass's type. When nothing calls it, every direct subclass gets a copy. An abstract method is removed instead, and each subclass's implementation stays as an ordinary method.
Redirect Calls with Constant Argument
Makes calls that pass a constant for a parameter call, directly, the method the original runs for that value. When SetValue(string name, int value) calls SetHeight(value) for "height", box.SetValue("height", 10) becomes box.SetHeight(10). Replace Parameter with Explicit Methods uses it once the branches have methods of their own.
Remove Delegating Member
Removes a member that only forwards, through base, to the inherited member it hides or overrides, so its callers reach the inherited member directly. Replace Delegation with Inheritance uses it once a class's forwarding members reach their targets through base.
Remove Redundant Else
Removes the else of an if whose branch always jumps away, so the else's statements follow the if: if (a) { return A(); } else { B(); } becomes if (a) { return A(); } followed by B();.
Remove Unused Parameter
Removes a parameter that no body reads, together with the argument every call passes for it.
Rename
Gives a symbol a new name and updates every reference to it across the solution.
Rename File to Match Type
Renames a source file after the single top-level type it declares, so that Ledger.cs holding class Account becomes Account.cs.
Replace Base Uses with Field
For a class that derives from another and holds a new instance of it in a private field: the class's own uses of the members it inherits go through the field instead, so nothing uses the part of the instance its base class makes up. Replace Inheritance with Delegation uses it just before removing the base class.
Replace Constructor with Factory Method
Adds a static factory method that calls a constructor, narrows the constructor, and makes every creation in the solution call the factory.
Replace Expression with Field
Replaces an expression in a member with a readonly field that holds an equivalent value: every constructor assigns the field from a parameter, and every construction of the class passes an equivalent expression for that parameter. Constructor Injection's recipe uses it to replace the object a method constructs with the one the class receives.
Replace Field Uses with Base
For a class that derives from another and also holds a new instance of it in a private field: uses of the field's members become uses of the members the class inherits, and the field is removed, so the instance itself takes the field's place. Replace Delegation with Inheritance uses it once the class derives from the field's class.
Safe Delete Local
Deletes a local variable that nothing uses, keeping whatever its initializer did beyond producing a value.
Safe Delete Member
Deletes a method, property, indexer, field or event that nothing uses.
Safe Delete Type
Deletes a class, struct, record, interface, enum or delegate that nothing uses, and the file it was alone in.
Split Declaration and Assignment
Turns a local declaration with an initializer into a declaration without one, followed by an assignment of the same value: var x = e; becomes T x; and x = e;. The reverse of Join Declaration and Assignment.
Split If
Splits an if whose condition is joined by && or || into two if statements, the reverse of Merge Nested If and of Consolidate Conditional Expression.
Split Temporary Variable
Gives a local that is reassigned for an unrelated purpose a new local from that reassignment on. The assignment becomes the declaration of a new local, and the uses after it refer to the new local. Applied once per reassignment, it leaves one local per purpose.
Sync Namespace with Folder
Sets the namespace of a file to the one its location implies: the project's root namespace followed by the folders between the project and the file. Billing/Taxes/Rate.cs in a project whose root namespace is Shop gets the namespace Shop.Billing.Taxes.
Use Named Arguments
Names the arguments of one call after the parameters they are passed for.
Use Pattern Matching
Replaces a type test followed by casts, or an as conversion followed by a null check, with a declaration pattern in the if statement.
Composites 24
Refactorings built as a recipe of primitive steps.
Collapse Hierarchy
Merges a class and its base class into one when they are no longer different enough to be kept apart: a subclass into its base class, or a base class into its only subclass.
Consolidate Conditional Expression
Combines a run of conditions that lead to the same code into one condition, and optionally gives it a name by extracting it into a method.
Constructor Injection
Turns an object a method constructs for itself into a dependency the class receives through its constructor and keeps in a field. Every construction of the class passes a new instance, built as the method built it.
Convert If to Switch Expression
Turns an if / else if chain that compares one value with constants or patterns, and whose branches each produce a value, into a switch expression that is returned or assigned.
Convert to Async
Makes a method that blocks on tasks async: it awaits them instead and returns a task. Its callers await it and become async in turn, repeating up to callers that cannot be async, which go on blocking on the task.
Decompose Conditional
Extracts the condition of an if statement into a method that names it, and each branch into a method that names what it does, so the statement reads as a sentence.
Extract Class
Splits a class that does two jobs: some of its fields, properties and methods move into a new class, and the old class keeps a field holding an instance of it and reaches the moved members through that field.
Extract Superclass
Gives a class a new base class and moves some of its fields and methods up into it, so that other classes can later share them by deriving from it too.
Hide Delegate
Stops clients reaching through one object to another. When clients write person.Department.Manager, the person gains a Manager member that forwards to its department, and the clients write person.Manager, so they no longer depend on the department.
Inline Class
Moves every member of a class that is not pulling its weight into the one class that holds an instance of it, and deletes it. The reverse of Extract Class.
Introduce Interface for Dependency
Makes a class depend on an interface instead of a concrete class: the interface is extracted from the concrete class, and the field, property or parameter holding the dependency is declared as the interface. Callers keep passing the concrete class, which now implements the interface.
Introduce Parameter Object
Replaces a group of parameters that travel together with one parameter of a new positional record holding them. The body reads the record's properties, and every call builds the record from the arguments it passed.
Make Static then Move
Moves an instance method to another class as a static method that takes the instance as a parameter. Useful for moving a method out of a large class when it has no field or parameter of the target type to move through.
Move Multiple Methods
Moves several methods of a class to another type in one operation: each instance method through a field, property or parameter of the target type, each static method to the target type by name.
Parameterise Method
Replaces several methods that do the same thing with different literal values by one method that takes those values as parameters, and makes every call pass the values of the method it called.
Preserve Whole Object
Replaces parameters that every call fills from members of one object with a single parameter taking the object, and reads the members in the body.
Remove Middle Man
Removes the members of a class that only pass requests on to another object it holds, so that callers talk to that object directly. The reverse of Hide Delegate.
Replace Delegation with Inheritance
For a class that holds an object of another class and forwards most of its members to it: the class derives from the other class instead, the members that only forwarded are removed so the inherited ones take their place, and the field goes.
Replace Inheritance with Delegation
For a class that inherits from another only to reuse some of its members: the class holds an instance of its old base class in a field, reaches what it used to inherit through the field, forwards the inherited members other code uses, and stops deriving from the old base class.
Replace Method with Method Object
Turns a long method whose locals get in the way of Extract Method into an object of its own. The instance, each parameter and each local become fields of a new class, so the body can then be split into methods that share them without passing them around. The old method creates one of these objects for each call and runs it.
Replace Nested Conditional with Guard Clauses
Flattens nested conditionals so that each special case is checked by a guard clause that leaves early, and the normal path runs unindented after them.
Replace Parameter with Explicit Methods
Gives each value a method dispatches on a method of its own, and makes calls that pass the value as a constant call that method directly. SetValue("height", 10) becomes SetHeight(10).
Replace Temp with Query
Replaces a local variable that holds the result of an expression with a private method that computes it, and calls the method wherever the local was read.
Separate Query from Modifier
Splits a method that both changes state and returns a value into a modifier that makes the change and a query that returns the value, and makes every caller call both. Afterwards asking for the value no longer changes anything.
Generators 12
Refactorings that generate new structure around existing code.
Add Null Checks
Adds an argument null guard at the start of a method or constructor for each reference-type parameter that is meant never to be null.
Add Observer / Event
Declares an event on a method's class and raises it whenever the method completes, so other objects can observe the change the method makes without the class knowing about them.
Convert to Nullable-Aware
Enables nullable reference types in one file and adds the ? annotations its code shows it needs, so the file compiles without new warnings. Files are converted one at a time, so a project can move to nullable gradually.
Create Adapter
Generates an adapter: a class that implements an interface a client expects by wrapping an existing class, the adaptee, and forwarding each interface member to the adaptee member that does the same job.
Extract Decorator
Generates a decorator for an interface: a class that implements the interface, wraps another implementation of it, and forwards every member to the wrapped instance. Behaviour is then added by editing the decorator's members, and callers opt in by wrapping an instance.
Feature Flag Wrapping
Replaces an if on a feature flag with strategies: each branch moves into the Apply method of its own class, and a property named after the flag checks it and returns the strategy to apply. The flag then decides between two objects in one place instead of guarding code inline, and the old path can later be deleted by deleting a class.
Introduce Null Object
Generates a class that implements a field's interface by doing nothing, makes the field hold it instead of null, and removes the field's null checks across the solution.
Replace Array with Object
Replaces an array whose elements mean different things, such as a name at index 0 and a score at index 1, with a new class that has a named property for each index.
Replace Conditional with Polymorphism
Replaces a method whose body chooses what to do by the kind of object it is dealing with, with a method each subclass overrides. The conditional can test either:
Replace Error Code with Exception
Makes a method that reports failure through its return value return nothing and throw instead, and turns each caller that tested the value into a try/catch.
Replace Type Code with Enum
Replaces a set of int or string constants that name kinds of something, such as Employee.Engineer = 0 and Employee.Manager = 1, with an enum, and retypes every declaration that carries one of those codes.
Replace Type Code with Subclasses
Replaces an enum field that says what kind of object an instance is with a subclass per kind. Each object's class then carries its kind, so Replace Conditional with Polymorphism can move the behaviour that switches on it into the subclasses.