Skip to content

Repository files navigation

C# Essentials

Essential refactoring tools and quality-of-life improvements for C# developers in VS Code.

Features

Extract Interface

  • 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 Method to 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 Property to Interface

  • 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

Implement Interface

  • 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)

Sync Interface with Class

  • 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 Constructor

  • 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

Encapsulate Field

  • 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 Checks

  • 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

Introduce Field

  • 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 Method

  • 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

Usage

Extract Interface

  1. Open a C# file in VS Code.
  2. Press Ctrl + . on a class keyword (place the cursor on it).
  3. In the context menu, select "Extract Interface".
  4. Enter a name for the new interface (default is I followed by the class name).
  5. 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.

Example

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; }
}

Add Method to Interface

  1. Open a C# file that implements an interface.
  2. Press Ctrl + . on a public method.
  3. Select "Add 'MethodName' to Interface".
  4. If the class implements multiple interfaces, select which one to add the method to.
  5. The method signature will be added to the interface file.

Add Property to Interface

  1. Open a C# file that implements an interface.
  2. Press Ctrl + . on a public property.
  3. Select "Add 'PropertyName' to Interface".
  4. If the class implements multiple interfaces, select which one to add the property to.
  5. The property signature will be added to the interface file.

Implement Interface

  1. Open a C# class that declares it implements an interface (e.g., public class MyClass : IMyInterface).
  2. Press Ctrl + . on the class declaration.
  3. Select "Implement 'InterfaceName'".
  4. If the class implements multiple interfaces, each will be shown as a separate option.
  5. The extension will generate stubs for all unimplemented members.

Example

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();
    }
}

Sync Interface with Class

  1. Open a C# class that implements an interface.
  2. Press Ctrl + . on the class declaration.
  3. Select "Sync 'InterfaceName' with Class".
  4. All public members in the class that aren't in the interface will be added.

Example

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();
}

Generate Constructor

  1. Open a C# class that has private/protected fields.
  2. Press Ctrl + . on the class declaration.
  3. Select "Generate Constructor".
  4. A constructor will be generated with parameters for all fields.

Example

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;
    }
}

Encapsulate Field

  1. Open a C# class that has private/protected fields.
  2. Press Ctrl + . on a field declaration.
  3. Select "Encapsulate Field '_fieldName'".
  4. A public property will be generated that wraps the field.

Example

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;
    }
}

Add Null Checks

  1. Open a C# file with a method or constructor that has reference type parameters.
  2. Press Ctrl + . on the method/constructor declaration line.
  3. Select "Add Null Checks".
  4. Null check statements will be added at the beginning of the method body.

Example

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;
}

Introduce Field

  1. Open a C# file with a method that has local variable declarations.
  2. Press Ctrl + . on a local variable declaration line.
  3. Select "Introduce Field '_variableName'".
  4. The variable will be converted to a class-level field.

Example

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);
    }
}

Extract Method

  1. Open a C# file and select one or more lines of code inside a method.
  2. Press Ctrl + . with the code selected.
  3. Select "Extract Method".
  4. Enter a name for the new method.
  5. The selected code will be moved to a new method and replaced with a method call.

Example

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}");
    }
}

Troubleshooting

I don't see the "Extract Interface" option in the context menu.

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.

The generated interface is not updating the class.

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.

About

No description, website, or topics provided.

Resources

Stars

3 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages