I like to adhere to StyleCop's formatting rules to make code nice and clear, but I've recently had a problem with one of its warnings:
All using directives must be placed
inside of the namespace.
My problem is that I have using directives, an assembly reference (for mocking file deletion), and a namespace to juggle in one of my test classes:
using System;
using System.IO;
using Microsoft.Moles.Framework;
using Microsoft.VisualStudio.TestTools.UnitTesting;
[assembly: MoledType(typeof(System.IO.File))]
namespace MyNamespace
{
//Some Code
}
The above allows tests to be run fine - but StyleCop complains about the using directives not being inside the namespace.
Putting the usings inside the namespace gives the error that "MoledType" is not recognised.
Putting both the usings and the assembly reference inside the namespace gives the error
'assembly' is not a valid attribute
location for this declaration. Valid
attribute locations for this
declaration are 'type'. All attributes
in this block will be ignored.
It seems I've tried every layout I can but to no avail - either the solution won't build, the mocking won't work or StyleCop complains!
Does anyone know a way to set these out so that everything's happy? Or am I going to have to ignore the StyleCop warning in this case?
Solved two minutes later!
I just needed to put the full path of "MoledType" in the assembly reference - meaning I could leave it outside of the namespace with the using directives inside like so:
[assembly: Microsoft.Moles.Framework.MoledType(typeof(System.IO.File))]
namespace MyNamespace
{
using System;
using System.IO;
using Microsoft.Moles.Framework;
using Microsoft.VisualStudio.TestTools.UnitTesting;
// Some Code...
}
Hopefully someone'll find this useful!
The typical pattern would be to put all of your Assembly level attributes within the AssemblyInfo.cs file. Typically this file does not have any namespace element at all and all of the assembly attributes are defined using fully qualified names.
Agreed with Jason, you should put this in the AssemblyInfo.cs instead (Project -> Properties).
But! Be careful with what you put in the AssemblyInfo.cs file. Say you want to use:
[assembly: InternalsVisibleTo("ClassA")]
If you put this in AssemblyInfo.cs, ALL internal classes of the project will be visible to ClassA. This is not always wanted.
Related
I am creating a NUnit test project and in the creation of that, MS Visual Studio has created a file called Usings.cs with the line
global using NUnit.Framework;
which tells the project to include the NUnit framework in every file.
I have been running StyleCopAnalyzers over this test project, and it keeps reporting
SA1200: Using directive should appear within a namespace declaration.
However, when I put the global using within a namespace declaration
namespace TestProject
{
global using NUnit.Framework;
}
I get the error
CS8914: A global using directive cannot be used in a namespace declaration.
What is the correct approach? Should I use the Usings.cs file with global usings?
In your .csproj add the following lines
<ItemGroup>
<Using Include="NUnit.Framework" />
</ItemGroup>
Hopefully an elementary question, but one to which I can't find an answer...
This Microsoft documentation leads me to believe that I need to add a using directive for my main project's namespace to my test class files, in order to be able to access the main project's members.
using MainProject;
namespace MainProject.Tests;
[TestClass]
public class UnitTests
{
...
}
However, when I do so, Visual Studio Code (with the Microsoft C# extension) tells me the MainProject import is unnecessary. And indeed, my unit tests manage to access the main project members without the using statement.
Both the main project and the test project exist in separate directories and have separate .csproj files. Both live inside a parent folder containing an .sln file to which each has been added. The test project's .csproj file has a reference to the main project's.
The main project's namespace is: MainProject
The test project's namespace is: MainProject.Tests
I have opted into global usings in the test project file, and there is a usings.cs file, which contains one line:
global using Microsoft.VisualStudio.TestTools.UnitTesting;
Where is the magic happening? (For example, is there a rule that the "child" namespace automatically "inherits" the types declared in the parent?)
Many thanks for your help.
A usising statement simple brings the namespace in scope for name resolution, it has nothing to do with directories or assemblies.
The namespace does the same thing, except it has a hierarchical basis and so isn’t as flexible.
In essence, there is no magic, you have misunderstood what is happening.
I found the official documentation explaining that namespace scopes "nest", and that the inner namespace has access to the members of the outer. Here it is:
https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/basic-concepts#77-scopes
(The second bullet point in section 7.7.1 describes the rule.)
When I last worked with C#, a long time ago, it was similar enough to Java to be virtually indistinguishable. But a lot has changed.
For example, I had forgotten that the Java-style namespace declarations are a recent addition to dotnet:
namespace MyCompany.MyProduct;
...
We used to have to do it like this:
namespace MyCompany
{
namespace MyProduct
{
...
}
}
Looking at it this way, it's easy to see why one might implicitly presume that the inner scope has access to the members of the outer, without having to read the rule from the language spec. If you're used to JavaScript scopes, for example, and your mental model of namespaces looks like the above, then the idea just seems natural.
However, if you're used to the way package imports work in Java, then this can seem very strange.
I'm working on app which uses a lot of external assemblies (newtonsoft.dll, Yahoo Yui compressor.dll, fleck.dll etc). In each c# file I need to add using statement with all those assemblies. Is it possible to create my own assembly (i.e. LIBRARY.dll) containing all the dll's and refer only to this in all c# files?
No. Firstly, using directives refer to namespaces, not assemblies (assembly references are defined at the project level). Secondly: you almost certainly don't actually need all of them in every file. But: you can create a new-file-template with the ones you are likely to need. But frankly it is usually easier to either copy/paste them, or just add them when they are needed. In the IDE, this is as simple as pressing ctrl+.,ret after a type name that doesn't resolve... so MySpecialTypectrl+.,ret should add the missing using directive to resolve MySpecialType.
using does not refer to assembly, but to namespace. So the answer is "no"...
using System; // you are using items in the System namespace
using System.IO; // you are using items in the System.IO namespace
No. Usages of individual types need to be resolved to the namespaces where they are defined in. So, you will still need to include the resolution paths in your usings.
I wasn't able to set my new form as a startup form, it complained about it not existing.
But after some minutes I tried with typing "Namespace.NewForm" and that worked.
In my other project, The startup is set as this:
Application.Run(new MyForm());
Why did I have to specify namespace when changing startup form in this project?
Presumably because you didn't have a using directive for it:
using SomeNamespace;
...
Application.Run(new SomeForm());
There's nothing particularly different about the code used to call Application.Run - it's just normal C# code, following the normal rules of C#.
Use a using directive so you do not have to fully qualify the types within the namespace in question.
using MyNameSpace;
It's also worth pointing out that using directives in C# do not give you access to namespaces nested in the namespace you specify (just in case you are wondering). This means that
using System;
does not give you access to System.IO
It sounds like there's more context here than you're sharing. Regardless of what you're doing, any place where you reference MyForm will need to be able to resolve that reference to a fully-qualified class (including namespace). This means that it will either need to be fully-qualified or it will need its namespace included in the using statements at the top of the file (and be unambiguous).
Does your "working" version already have the using directive and the "non-working" version simply does not? Do your versions attempt to set the startup form in different places?
I suspect that the "working" version has the using directive already in place and that, for whatever reason, it's not in place in the "non-working" version.
seWhen i creating a new class file i got these namespaces by default,
using System;
using System.Data;
using System.Configuration;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
But i dont use linq,Html controls,Webcontrols,Configuration,security...
Why are they included by default?
What will happen if i exclude these from my class file?
What will happen if i include these without using them?
Why are they included by default?
Visual Studio adds a list of common includes to any class file that you create. Since it is an ASP.Net project, this is the list of using statement added to your file. For WinForms projects, it is a different set of usings.
What will happen if i exclude these from my class file?
If you don't use any classes within these namespaces within your file, excluding them will have no effect. If you use a class within those namespaces, you will have a compile error.
What will happen if i include them without using them?
Maybe it will take a few milliseconds longer to compile that file but I'm not even sure.
These namespaces are included by default in files that you add to an ASP.Net project.
The using statement simply tells the compiler which namespaces the classes you're using are in.
If you aren't using any classes from those namespaces, the using statement will no effect whatsoever; removing them or keeping them will not matter.
Caveat: If there are two classes with the same name in two different namespaces (eg, System.Windows.Forms.Control and System.Web.UI.Control), and you having using statements for both namespaces, you won't be able to use the class unless you fully qualify it with the namespace name. (Because the compiler cannot know which one you want)
Nothing will happen if you exclude them.
Nothing will really happen if you include them.
It's recommended to remove the ones you don't need.
Not sure about the Web stuff, but Linq is included by default for all 3.5 applications, probably because it's assumed that you'll use them as much as you do system.