Dotnet logo

The .NET Tools Blog

Essential productivity kit for .NET developers


R2P: A General-Purpose ReSharper Plugin

R2P (short for ‘Refactoring to Patterns’) is a plugin that embodies a collection of features of a fairly experimental nature. It does not have a single theme but, rather, tries to do different things in different areas of ReSharper. Let’s take a look at some of the things it does.

String Mutations

One of the key features of R2P is the ability to transform string literals. For example, the string splicing feature brings PHP-style string splicing to C#. Simply use the curly braces to delimit variables and R2P will offer a suitable context action:

Applying the action replaces the string with a string.Format() call, with the variables moved to the argument list:

R2P supports several transformations from strings to .NET types. For example, you can define time as a string and convert it to DateTime:

After invocation, the declaration is replaced with the following:

R2P supports transformations from string literals into the following types:

  • DateTime

  • TimeSpan

  • XElement

R2P also comes with a menu item called Paste Verbatim String that pastes strings from the clipboard with correct escapement. This facilitates transformations from strings into something else: for example, you can copy a block of XML from some app, paste it, then use the Convert to XElement context action to turn it into a fully object-oriented declaration.

In addition to the above, the plugin also supports a few string manipulations, such as:

  • HTML-encoding/decoding of a string.

  • String obfuscation using base64 encoding.

Code Generation

The plugin comes with several generators, which all embed themselves into the Generate menu:

  • Binary read/write members — for a given class, generates ReadFrom() and WriteTo() methods that use BinaryReader and BinaryWriter respectively and serialize chosen fields. Special care is taken when serializing known .NET types: for example, for a DateTime, only its Ticks property is serialized:

  • Copy constructor — for a given class creates a constructor that takes this class as a parameter and performs a copy of its properties/fields to the owner class.

  • Disposing members — in addition to being able to correctly identify all disposable fields and generate the appropriate Dispose() declaration, R2P’s implementation also offers to implement the full Dispose pattern.

  • Read-only interface — for a given class Foo, generates an interface IFoo where all properties are exposed as get-only, effectively creating a read-only interface contract for this class.

Code Inspections

R2P comes with several computation-related inspections, such as:

  • Inspections that detect inefficient Math.Pow() calls and refactor them to unline multiplication:

  • An inspection and corresponding context action that allows factoring out of common subexpressions:

  • Inspections and fixes relating to possible use of MAD (multiply-add) instruction when using GPU.NET:

In addition, R2P can help correct misspelt identifiers based on information about the available types:

Odds and Ends

R2P comes with a lot more functionality than we can list here. Some of its features include:

  • Refactorings such as Make Singleton (implements the Singleton pattern) and Enum to Class (turns an enumeration into a class with enum cases transformed to member variables).

  • Unit testing helpers such as being able to Assert on all public properties of an object instance, an ability to add a value as a Row in data-driven testing, and a Visual row editor.

  • General-purpose context actions such as code contract generators (generate code contract specifications for parameters), an action to make a method fluent (i.e., return this), and even a context action to treat the ^ operator as a power function.

  • A String format helper window that lets the user build a format string and preview the end result.

  • … and a lot more

R2P is distributed under a commercial license. For more information, head over to its product site and stay tuned for more plugin reviews!

Comments below can no longer be edited.

5 Responses to R2P: A General-Purpose ReSharper Plugin

  1. Avatar

    Patrick Smacchia says:

    January 16, 2013

    Very interesting, still, I dislike Make Singleton. 99% of Singleton usage are code smell that prevents code to be tested properly.

  2. Avatar

    Dmitri Nesteruk says:

    January 16, 2013

    @Patrick: you’re absolutely right. In fact, when the GoF were interviewed recently and asked what patterns they’d change, they said none except maybe remove Singleton. The accepted practice in .NET circles is to have single-instance lifetimes managed by an IoC container.

  3. Avatar

    Joe White says:

    January 18, 2013

    They’ve got a bunch of features that I wouldn’t want in the way (like “move usings into namespace”, which I don’t want, and which most everybody gets wrong anyway by forgetting to add “global::”). Does anyone know whether you can disable the features you don’t want cluttering up your context menus? And whether you can share those “what’s-disabled” lists in the .DotSettings team-shared file?

    “Enum to Class” definitely looks interesting, though. That’s a painful refactoring, especially if you have code that casts those enums to ints to store them in the database. Can R2P turn those casts into some corresponding OO code? If so, then that alone would be well worth the price of admission.

  4. Avatar

    Dmitri Nesteruk says:

    January 18, 2013

    @Joe: no, the “move usings” feature is built in, and not configurable. The enum to class will not alter usages, the idea being that code should not really break. As a result, you may end up having some redundant casts that are fairly easy to detect and remove.

  5. Avatar

    John Black says:

    March 8, 2013

    Implementing IDisposable with with Dispose(bool) is only required if the class has unmanaged fields. Otherwise it is considered an antipattern. Please see

    Perhaps R2P (or R# in general) could intelligently check whether Dispose(bool) is required or not?

Discover more