Essential refactoring tools and quality-of-life improvements for C# developers in VS Code.
- Extract interfaces from C# classes
- Automatically generate the interface in the same directory as the class
- Update the class to implement the newly created interface
- Option to provide a custom name and path for the interface
- Add a public method from a class to an interface it implements
- Automatically finds interface files in the workspace
- Supports multiple interfaces (prompts for selection)
- Prevents duplicate method signatures
- Add a public property from a class to an interface it implements
- Supports all property types including generics and nullable types
- Automatically finds interface files in the workspace
- Prevents duplicate property signatures
- Generate stub implementations for all interface members
- Automatically detects unimplemented methods, properties, and events
- Generates proper method stubs with
throw new NotImplementedException() - Supports multiple interfaces (select which one to implement)
- Update an interface to include all public members from the implementing class
- Detects methods, properties, and events in the class that aren't in the interface
- Adds missing members to the interface file automatically
- Useful when you've added new members to a class and need to update the interface
- Generate a constructor that initializes all fields in a class
- Automatically creates parameters from field names (removes underscore prefix)
- Inserts constructor after field declarations
- Only appears when class has fields and no existing constructor
- Convert a private field to a property with a backing field
- Automatically generates property name from field name (
_name→Name) - Readonly fields get expression-bodied properties (
=> _name) - Non-readonly fields get full get/set properties
- Add null argument checks to method or constructor parameters
- Automatically detects reference type parameters that need checking
- Generates
if (param == null) throw new ArgumentNullException(...)statements - Skips parameters that already have null checks
- Convert a local variable to a class-level field
- Automatically generates field name with underscore prefix (e.g.,
name→_name) - Replaces variable declaration with field assignment
- Inserts field at the top of the class with other fields
- Extract selected code into a new method
- Automatically detects variables that need to be passed as parameters
- Handles return values for variables used after the selection
- Prompts for method name with validation
- Open a C# file in VS Code.
- Press
Ctrl + .on aclasskeyword (place the cursor on it). - In the context menu, select "Extract Interface".
- Enter a name for the new interface (default is
Ifollowed by the class name). - The extension will:
- Generate an interface with all public methods of the class.
- Create the interface in the same directory as the class.
- Modify the class to implement the new interface.
Given a class like this:
public class DiceManager
{
public void RollDice() { }
public int GetScore() { return 0; }
}After clicking on "Extract Interface", it will generate the following interface:
public interface IDiceManager
{
void RollDice();
int GetScore();
}The DiceManager class will be updated to:
public class DiceManager : IDiceManager
{
public void RollDice() { }
public int GetScore() { return 0; }
}- Open a C# file that implements an interface.
- Press
Ctrl + .on a public method. - Select "Add 'MethodName' to Interface".
- If the class implements multiple interfaces, select which one to add the method to.
- The method signature will be added to the interface file.
- Open a C# file that implements an interface.
- Press
Ctrl + .on a public property. - Select "Add 'PropertyName' to Interface".
- If the class implements multiple interfaces, select which one to add the property to.
- The property signature will be added to the interface file.
- Open a C# class that declares it implements an interface (e.g.,
public class MyClass : IMyInterface). - Press
Ctrl + .on the class declaration. - Select "Implement 'InterfaceName'".
- If the class implements multiple interfaces, each will be shown as a separate option.
- The extension will generate stubs for all unimplemented members.
Given an interface:
public interface IDataService
{
int Id { get; set; }
event EventHandler DataChanged;
Task<string> GetDataAsync(int id);
}And a class that doesn't implement it yet:
public class DataService : IDataService
{
}After clicking on "Implement 'IDataService'", the class will be updated to:
public class DataService : IDataService
{
public int Id { get; set; }
public event EventHandler DataChanged;
public Task<string> GetDataAsync(int id)
{
throw new NotImplementedException();
}
}- Open a C# class that implements an interface.
- Press
Ctrl + .on the class declaration. - Select "Sync 'InterfaceName' with Class".
- All public members in the class that aren't in the interface will be added.
Given a class with new members:
public class DataService : IDataService
{
public int Id { get; set; }
public string Name { get; set; } // New property
public event EventHandler Updated; // New event
public void Process() { } // New method
}And an interface that's out of date:
public interface IDataService
{
int Id { get; set; }
}After clicking on "Sync 'IDataService' with Class", the interface will be updated to:
public interface IDataService
{
int Id { get; set; }
string Name { get; set; }
event EventHandler Updated;
void Process();
}- Open a C# class that has private/protected fields.
- Press
Ctrl + .on the class declaration. - Select "Generate Constructor".
- A constructor will be generated with parameters for all fields.
Given a class with fields:
public class UserService
{
private readonly ILogger _logger;
private readonly IRepository _repository;
}After clicking on "Generate Constructor", the class will be updated to:
public class UserService
{
private readonly ILogger _logger;
private readonly IRepository _repository;
public UserService(ILogger logger, IRepository repository)
{
_logger = logger;
_repository = repository;
}
}- Open a C# class that has private/protected fields.
- Press
Ctrl + .on a field declaration. - Select "Encapsulate Field '_fieldName'".
- A public property will be generated that wraps the field.
Given a class with a field:
public class UserService
{
private readonly ILogger _logger;
}After clicking on "Encapsulate Field '_logger'", the class will be updated to:
public class UserService
{
private readonly ILogger _logger;
public ILogger Logger => _logger;
}For non-readonly fields, a full property with getter and setter is generated:
public class Counter
{
private int _count;
public int Count
{
get => _count;
set => _count = value;
}
}- Open a C# file with a method or constructor that has reference type parameters.
- Press
Ctrl + .on the method/constructor declaration line. - Select "Add Null Checks".
- Null check statements will be added at the beginning of the method body.
Given a constructor:
public class UserService
{
private readonly ILogger _logger;
private readonly IRepository _repository;
public UserService(ILogger logger, IRepository repository)
{
_logger = logger;
_repository = repository;
}
}After clicking on "Add Null Checks", the constructor will be updated to:
public UserService(ILogger logger, IRepository repository)
{
if (logger == null)
{
throw new ArgumentNullException(nameof(logger));
}
if (repository == null)
{
throw new ArgumentNullException(nameof(repository));
}
_logger = logger;
_repository = repository;
}- Open a C# file with a method that has local variable declarations.
- Press
Ctrl + .on a local variable declaration line. - Select "Introduce Field '_variableName'".
- The variable will be converted to a class-level field.
Given a method with a local variable:
public class DataProcessor
{
public void Process()
{
string data = GetData();
Console.WriteLine(data);
}
}After clicking on "Introduce Field '_data'", the class will be updated to:
public class DataProcessor
{
private string _data;
public void Process()
{
_data = GetData();
Console.WriteLine(_data);
}
}- Open a C# file and select one or more lines of code inside a method.
- Press
Ctrl + .with the code selected. - Select "Extract Method".
- Enter a name for the new method.
- The selected code will be moved to a new method and replaced with a method call.
Given a method with code to extract:
public class Calculator
{
public void Calculate()
{
int x = 10;
int y = 20;
int sum = x + y;
Console.WriteLine($"Sum: {sum}");
}
}After selecting lines 6-7 and clicking "Extract Method" with name "PrintSum":
public class Calculator
{
public void Calculate()
{
int x = 10;
int y = 20;
PrintSum(x, y);
}
private void PrintSum(int x, int y)
{
int sum = x + y;
Console.WriteLine($"Sum: {sum}");
}
}Make sure you're pressing Ctrl + . on the class declaration (public class <ClassName>) in the editor. If you are on a method or variable, the option won't appear.
If Ctrl + . doesn't work, try right-clicking on the class declaration and selecting "Extract Interface" from the context menu.
Ensure that the class is being correctly identified by the extension. If the class is not in the format public class <ClassName>, or if it's in a file that doesn't follow standard C# conventions, the extension may not function as expected.