Visual Studio 2015

C# 6 Verbatim Interpolated String Literals

It’s no secret that string interpolation is one of my favorite C# 6 language features because of how well it cleans up that messy composite formatting syntax. A few days ago I was working on some code that contained a verbatim string that included a few of the classic tokens and I wondered if string interpolation would work with verbatim strings as well.

After a quick glance over the MSDN documentation for string interpolation revealed nothing I just decided to give it a shot by adding a dollar sign ($) ahead of the existing at (@) sign and filled the holes with the appropriate expressions. Much to my delight this worked beautifully as shown in the snippet below!

var name = "Dave";
var age = 36;

var sentence = $@"Hello!
My name is {name}.
I'm {age} years old.";

Console.WriteLine(sentence);

I later discovered that even though this feature doesn’t seem to be listed in the MSDN documentation (at least anywhere I could find it) that it is explicitly called out in the C# 6 draft specification so hopefully it’ll find its way to the rest of the documentation at some point.

Advertisements

Crashing Visual Studio 2015 with Explicit Interface Implementations

In F#, all interface implementations are always explicit meaning that the interface methods will only be accessible when treating the implementing type as that interface. This makes sense in F# because it removes all ambiguity around what the method applies to. Explicit implementations also force us into coding to the interface because other miscellaneous members of the implementing type aren’t exposed through the interface definition. For these reasons I’ve been hooked on explicit interface implementation and even use it almost exclusively with great success in my C# applications.

Imagine my surprise then when Visual Studio 2015 crashed when I tried to rename an explicitly implemented interface method! The first time it happened I figured it was probably just Visual Studio misbehaving but when I reopened the solution and tried again the same thing happened! Clearly there was something more to this.

RefactorCrash

Renaming an explicitly implemented interface method causes Visual Studio 2015 to crash.

Hoping that I’d perhaps stumbled upon something that was fixed and included in Update 1, I upgraded Visual Studio and tried again. The crash still occurred.

To narrow down the issue I created a brand new solution with a console application. Within the new project I defined a simple interface with a single method and explicitly implemented it in a class. At this point I attempted to rename the method and it worked as expected. I then tried renaming the interface method directly on the interface and that also worked as expected. Then I figured that it must have something to do with how the interface was being used so I created an instance of the class, converted it to the interface, and tried the rename again and it was successful. Finally, I added a line to invoke the interface method and tried the rename one more time. Oddly, it again worked as expected.

On a whim I decided to move the interface and implementation into a separate project. After adding the project reference and doing a test build I again tried to rename the method and sure enough, Visual Studio crashed. I’ve since played with a few different combinations and have been able to successfully recreate the crash as long as the interface is defined in a separate assembly and I tried renaming the method via the explicit implementation.

In summary, it appears that in order to recreate this crash the following conditions must be met:

  • Interface must be explicitly implemented
  • Interface must be defined in a separate assembly than where it’s used
  • Rename must be attempted against the explicit implementation
  • Interface method must be invoked – simply creating an instance won’t cause the crash.

I’ve submitted the issue to Microsoft on Connect but this seems like such an edge case I’d be surprised to see a fix anytime soon. In the mean time, if this is something you encounter you can safely rename the method on the interface itself or at the call site; neither of those seemed to be an issue.

If you’d like to mess around with this issue on your own, I’ve shared my sample project on GitHub.

Fun with Code Diagnostic Analyzers

A few days ago I posted an article detailing how to construct a code diagnostic analyzer and code fix provider to detect if..else statements that simply assign a variable or return a value and replace the statements with a conditional operator. You know, the kind of things that code diagnostic analyzers and code fix providers are intended for. As I was developing those components I got to thinking about what kind of fun I could have while abusing the feature. More specifically, I wondered whether could I construct a code diagnostic analyzer such that it would highlight every line of C# code as a warning and recommend using F# instead.

It turns out, it’s actually really easy. The trick is to register a syntax tree action rather than a syntax node action and always report the diagnostic rule at the tree’s root location. For an extra bit of fun, I also set the diagnostic rule’s help link to fsharp.org so that clicking the link in the error list directs the user to that site.

Here’s the analyzer’s code listing in its entirety:

using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Diagnostics;
using System.Collections.Immutable;

namespace UseFSharpAnalyzer
{
    [DiagnosticAnalyzer(LanguageNames.CSharp)]
    public class UseFSharpAnalyzerAnalyzer : DiagnosticAnalyzer
    {
        internal static DiagnosticDescriptor Rule =
            new DiagnosticDescriptor(
                "UseFSharpAnalyzer",
                "Use F#",
                "You're using C#; Try F# instead!",
                "Language Choice",
                DiagnosticSeverity.Warning,
                isEnabledByDefault: true,
                helpLink: "http://fsharp.org");

        public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics { get { return ImmutableArray.Create(Rule); } }

        public override void Initialize(AnalysisContext context)
        {
            context.RegisterSyntaxTreeAction(AnalyzeTree);
        }

        private static void AnalyzeTree(SyntaxTreeAnalysisContext context)
        {
            var rootLocation = context.Tree.GetRoot().GetLocation();
            var diag = Diagnostic.Create(Rule, rootLocation);

            context.ReportDiagnostic(diag);
        }
    }
}

When applied to a C# file, the result is as follows:

Use F# Analyzer

This is clearly an example of what not to do with code analyzers but it was fun to put together and see the result nonetheless. If you’ve thought of any other entertaining uses for code analyzers, I’d love to hear about them!

I Can Analyze Code, And So Can You

[12 December 2014 – Update 1] Upon setting up a new VM I realized that I missed a prerequisite when writing this post. The Visual Studio 2015 Preview SDK is also required. This extension includes the VSIX project subtype required by the Diagnostic and Code Fix template used for the example. I’ve included a note about installing the SDK in the prerequisites section below.

[12 December 2014 – Update 2] The github project has moved under the .NET Analyzers organization. This organization is collecting diagnostics, code fixes, and refactorings like to showcase the capabilities of this technology. The project link has been updated accordingly.

Over the past several years, Microsoft has been hard at work on the .NET Compiler Platform (formerly Roslyn). Shipping with Visual Studio 2015 the .NET Compiler Platform includes a complete rewrite of the C# and Visual Basic compilers intended to bring features that developers have come to expect from modern compilers. In addition to the shiny new compilers the .NET Compiler Platform introduces a rich set of APIs that we can harness to build custom code diagnostic analyzers and code fix providers thus allowing us to detect and correct issues in our code.

When trying to decide on a useful demonstration for these features I thought of one of my coding pet peeves: using an if..else statement to conditionally set a variable or return a value. I prefer treating these scenarios as an expression via the conditional (ternary) operator and I often find myself refactoring these patterns in legacy code. It certainly would be nice to automate that process. It turns out that this is exactly the type of task at which diagnostic analyzers and code fix providers excel and we’ll walk through the process of creating such components in this post. (more…)