Is there a way to enforce move usings inside namespace?

I am using Microsoft's StyleCop and there is a rule that requires usings to be encapsulated by the namespace. Is there a way I can enforce this behavior in ReSharper, or disable the default insert of usings to the top of the file and moving them back on a code cleanup?

Here is the StyleCop justification for the rule:

Rule Description
A violation of this rule occurs when a using directive or a using-alias directive is placed outside of a namespace element, unless the file does not contain any namespace elements.

For example, the following code would result in two violations of this rule.

using System;
using Guid = System.Guid;

namespace Microsoft.Sample
{
public class Program
{
}
}

The following code, however, would not result in any violations of this rule:

namespace Microsoft.Sample
{
using System;
using Guid = System.Guid;

public class Program
{
}
}

There are subtle differences between placing using directives within a namespace element, rather than outside of the namespace, including:

1. Placing using-alias directives within the namespace eliminates compiler confusion between conflicting types.

2. When multiple namespaces are defined within a single file, placing using directives within the namespace elements scopes references and aliases.

1. Eliminating Type Confusion

Consider the following code, which contains a using-alias directive defined outside of the namespace element. The code creates a new class called Guid, and also defines a using-alias directive to map the name Guid to the type System.Guid. Finally, the code creates an instance of the type Guid:

using Guid = System.Guid;

namespace Microsoft.Sample
{
public class Guid
{
public Guid(string s)
{
}
}

public class Program
{
public static void Main(string[] args)
{
Guid g = new Guid("hello");
}
}
}



This code will compile cleanly, without any compiler errors. However, it is unclear which version of the Guid type is being allocated. If the using directive is moved inside of the namespace, as shown below, a compiler error will occur:

namespace Microsoft.Sample
{
using Guid = System.Guid;

public class Guid
{
public Guid(string s)
{
}
}

public class Program
{
public static void Main(string[] args)
{
Guid g = new Guid("hello");
}
}
}



The code fails on the following compiler error, found on the line containing Guid g = new Guid("hello");

CS0576: Namespace 'Microsoft.Sample' contains a definition conflicting with alias 'Guid'

The code creates an alias to the System.Guid type called Guid, and also creates its own type called Guid with a matching constructor interface. Later, the code creates an instance of the type Guid. To create this instance, the compiler must choose between the two different definitions of Guid. When the using-alias directive is placed outside of the namespace element, the compiler will choose the local definition of Guid defined within the local namespace, and completely ignore the using-alias directive defined outside of the namespace. This, unfortunately, is not obvious when reading the code.

When the using-alias directive is positioned within the namespace, however, the compiler has to choose between two different, conflicting Guid types both defined within the same namespace. Both of these types provide a matching constructor. The compiler is unable to make a decision, so it flags the compiler error.

Placing the using-alias directive outside of the namespace is a bad practice because it can lead to confusion in situations such as this, where it is not obvious which version of the type is actually being used. This can potentially lead to a bug which might be difficult to diagnose.

Placing using-alias directives within the namespace element eliminates this as a source of bugs.

2. Multiple Namespaces

Placing multiple namespace elements within a single file is generally a bad idea, but if and when this is done, it is a good idea to place all using directives within each of the namespace elements, rather than globally at the top of the file. This will scope the namespaces tightly, and will also help to avoid the kind of behavior described above.

It is important to note that when code has been written with using directives placed outside of the namespace, care should be taken when moving these directives within the namespace, to ensure that this is not changing the semantics of the code. As explained above, placing using-alias directives within the namespace element allows the compiler to choose between conflicting types in ways that will not happen when the directives are placed outside of the namespace.

How to Fix Violations
To fix a violation of this rule, move all using directives and using-alias directives within the namespace element.

5 comments

No offense intended, and I'm all for seeing R# be flexible enough to support even the craziest of things, but the insanity of StyleCop just continues and continues. So, we're now supposed to believe that aliasing things overtop existing type names isn't a bad thing, and neither is declaring multiple types in a single file (which is the only way you could need to put multiple namespace declarations in a single file.) Those aren't justifications you listed there, they are anti-patterns. The more StyleCop rules I learn, the more obvious it is that StyleCop is one giant WTF. Just my not-so-humble opinion, of course. ;) Think of it instead as encouragement for your team to come up with their own coding standard. Preferably one that makes sense and wasn't assembled by committee from the conflicting preferences of literally thousands of developers. ;)

0

Hello Daren,

You may be want to read this blog post: http://www.hanselman.com/blog/BackToBasicsDoNamespaceUsingDirectivesAffectAssemblyLoading.aspx
And then may be change your mind about the StyleCop coolness ;)

Sincerely,
Ilya Ryzhenkov

JetBrains, Inc
http://www.jetbrains.com
"Develop with pleasure!"


IR> I am using Microsoft's StyleCop and there is a rule that requires
IR> usings to be encapsulated by the namespace. Is there a way I can
IR> enforce this behavior in ReSharper, or disable the default insert of
IR> usings to the top of the file and moving them back on a code
IR> cleanup?
IR>
IR> Here is the StyleCop justification for the rule:
IR>
IR> Rule Description A violation of this rule occurs when a using
IR> directive or a using-alias directive is placed outside of a
IR> namespace element, unless the file does not contain any namespace
IR> elements.
IR>
IR> For example, the following code would result in two violations of
IR> this rule.
IR>
IR> using System;
IR> using Guid = System.Guid;
IR> namespace Microsoft.Sample
IR> {
IR> public class Program
IR> {
IR> }
IR> }
IR> The following code, however, would not result in any violations of
IR> this rule:
IR>
IR> namespace Microsoft.Sample
IR> {
IR> using System;
IR> using Guid = System.Guid;
IR> public class Program
IR> {
IR> }
IR> }
IR> There are subtle differences between placing using directives within
IR> a namespace element, rather than outside of the namespace,
IR> including:
IR>
IR> 1. Placing using-alias directives within the namespace eliminates
IR> compiler confusion between conflicting types.
IR>
IR> 2. When multiple namespaces are defined within a single file,
IR> placing using directives within the namespace elements scopes
IR> references and aliases.
IR>
IR> 1. Eliminating Type Confusion
IR>
IR> Consider the following code, which contains a using-alias directive
IR> defined outside of the namespace element. The code creates a new
IR> class called Guid, and also defines a using-alias directive to map
IR> the name Guid to the type System.Guid. Finally, the code creates an
IR> instance of the type Guid:
IR>
IR> using Guid = System.Guid;
IR>
IR> namespace Microsoft.Sample
IR> {
IR> public class Guid
IR> {
IR> public Guid(string s)
IR> {
IR> }
IR> }
IR> public class Program
IR> {
IR> public static void Main(string[] args)
IR> {
IR> Guid g = new Guid("hello");
IR> }
IR> }
IR> }
IR> This code will compile cleanly, without any compiler errors.
IR> However, it is unclear which version of the Guid type is being
IR> allocated. If the using directive is moved inside of the namespace,
IR> as shown below, a compiler error will occur:
IR>
IR> namespace Microsoft.Sample
IR> {
IR> using Guid = System.Guid;
IR> public class Guid
IR> {
IR> public Guid(string s)
IR> {
IR> }
IR> }
IR> public class Program
IR> {
IR> public static void Main(string[] args)
IR> {
IR> Guid g = new Guid("hello");
IR> }
IR> }
IR> }
IR> The code fails on the following compiler error, found on the line
IR> containing Guid g = new Guid("hello");
IR>
IR> CS0576: Namespace 'Microsoft.Sample' contains a definition
IR> conflicting with alias 'Guid'
IR>
IR> The code creates an alias to the System.Guid type called Guid, and
IR> also creates its own type called Guid with a matching constructor
IR> interface. Later, the code creates an instance of the type Guid. To
IR> create this instance, the compiler must choose between the two
IR> different definitions of Guid. When the using-alias directive is
IR> placed outside of the namespace element, the compiler will choose
IR> the local definition of Guid defined within the local namespace, and
IR> completely ignore the using-alias directive defined outside of the
IR> namespace. This, unfortunately, is not obvious when reading the
IR> code.
IR>
IR> When the using-alias directive is positioned within the namespace,
IR> however, the compiler has to choose between two different,
IR> conflicting Guid types both defined within the same namespace. Both
IR> of these types provide a matching constructor. The compiler is
IR> unable to make a decision, so it flags the compiler error.
IR>
IR> Placing the using-alias directive outside of the namespace is a bad
IR> practice because it can lead to confusion in situations such as
IR> this, where it is not obvious which version of the type is actually
IR> being used. This can potentially lead to a bug which might be
IR> difficult to diagnose.
IR>
IR> Placing using-alias directives within the namespace element
IR> eliminates this as a source of bugs.
IR>
IR> 2. Multiple Namespaces
IR>
IR> Placing multiple namespace elements within a single file is
IR> generally a bad idea, but if and when this is done, it is a good
IR> idea to place all using directives within each of the namespace
IR> elements, rather than globally at the top of the file. This will
IR> scope the namespaces tightly, and will also help to avoid the kind
IR> of behavior described above.
IR>
IR> It is important to note that when code has been written with using
IR> directives placed outside of the namespace, care should be taken
IR> when moving these directives within the namespace, to ensure that
IR> this is not changing the semantics of the code. As explained above,
IR> placing using-alias directives within the namespace element allows
IR> the compiler to choose between conflicting types in ways that will
IR> not happen when the directives are placed outside of the namespace.
IR>
IR> How to Fix Violations
IR> To fix a violation of this rule, move all using directives and
IR> using-alias directives within the namespace element.


0

I wasn't offering nor asking for an opinion on whether I thought the rule to be sane, merely asking if R# could be configured to support it. I guess the answer is "No". For what it's worth, I loath the rule.

0

Hello Daren,

I think this is possible.

In Options, Namespace Imports, check the option "Add using directive to the
deepest scope" checkbox.

I had to ask a co-worker to find this option.

--Jakob

I wasn't offering nor asking for an opinion on whether I thought the
rule to be sane, merely asking if R# could be configured to support
it. I guess the answer is "No". For what it's worth, I loath the rule.



0

Please sign in to leave a comment.