What makes a particular using directive unnecessary? - c#

I have a solution with multiple projects.
Project A has namespace 1 which uses a particular class X and has a using directive for it. That project compiles.
Project B has class 2 (in namespace 2) which uses the same class X but does not compile because "The name X does not exist in the current context". If I include the using directive from class 1 I get "Using directive is unnecessary"
So there is something different about project A and B, where one needs the using directive and one doesn't.
There are clearly multiple issues with my solution here but first I want to understand what makes a using directive necessary or not. Where can I start looking?
Edited to clarify the text above a bit, and also add the following code snippets as requested.
Project A:
using Microsoft.WindowsAzure; //CloudConfigurationManager is here
using MyNamespace.MyClass; //Constants is here
namespace n1
{
private static string resourceId = CloudConfigurationManager.GetSetting("id");
Console.WriteLine($"{resourceId}{Constants.Blah}("blah")";
}
Project B:
using Microsoft.WindowsAzure; //directive unnecessary
using MyNamespace.MyClass; //directive unnecessary
namespace Testing
{
class Program
{
public static void Main(string[] args)
{
string resourceId = CloudConfigurationManager.GetSetting("id"); // The name CloudConfigurationManager does not exist in the current context
Console.WriteLine($"{resourceId}{Constants.Blah}("blah")"; // The name Constants does not exist in the current context
}
}
}

You need to add the using X class X in your Project B separately. Your using X from Project A isn't forwarded by only adding a using A.
If you would only use functions/classes from Class 1, which encapsulate functionality of class X you would be OK with only referencing class 1.
But in your case, as I understand it, you want to use X-functionality directly - hence the separate using directive.

Related

top-level namespace name starts with end of current namespace name [duplicate]

I believe I have a fundamental misunderstanding of namespace hierarchy, causing almost the opposite problem to this question: vb.net System namespace conflict with sibling namespace
I have two .cs files containing the below:
File 1
namespace Parent.Math
{
public class Foo { }
}
File 2
using System;
namespace Parent.Child
{
public class Bar
{
public Bar()
{
Console.WriteLine(Math.Sqrt(4));
}
}
}
File 2 presents the error: CS0234 - The type or namespace name 'Sqrt' does not exist in the namespace 'Parent.Math'
Why does the compiler assume Math to be reference to the sibling namespace and not the member of the explicitly referenced System namespace? The behavior is as if parent namespaces are automatically referenced. Is this correct? I would of at least expected an ambiguity error.
Thank you.
When you are in a namespace, the compiler always assume that you are in the parent namespace too.
Hence while being in Parent.Child, writing Math, the compiler search in Child and next in Parent and found Math as a namespace but no Sqrt type, so the error.
The compiler search like that and go up the chain of namespaces.
Without namespace, you are in global.
You can simply write:
Console.WriteLine(System.Math.Sqrt(4));
Or that in case of problem:
Console.WriteLine(global::System.Math.Sqrt(4));
You can also write:
using SystemMath = System.Math;
Console.WriteLine(SystemMath.Sqrt(4));
And since C# 6:
using static System.Math;
Console.WriteLine(Sqrt(4));
https://learn.microsoft.com/dotnet/csharp/language-reference/keywords/using-directive

How to avoid seemingly automatic reference of "parent" namespaces?

I believe I have a fundamental misunderstanding of namespace hierarchy, causing almost the opposite problem to this question: vb.net System namespace conflict with sibling namespace
I have two .cs files containing the below:
File 1
namespace Parent.Math
{
public class Foo { }
}
File 2
using System;
namespace Parent.Child
{
public class Bar
{
public Bar()
{
Console.WriteLine(Math.Sqrt(4));
}
}
}
File 2 presents the error: CS0234 - The type or namespace name 'Sqrt' does not exist in the namespace 'Parent.Math'
Why does the compiler assume Math to be reference to the sibling namespace and not the member of the explicitly referenced System namespace? The behavior is as if parent namespaces are automatically referenced. Is this correct? I would of at least expected an ambiguity error.
Thank you.
When you are in a namespace, the compiler always assume that you are in the parent namespace too.
Hence while being in Parent.Child, writing Math, the compiler search in Child and next in Parent and found Math as a namespace but no Sqrt type, so the error.
The compiler search like that and go up the chain of namespaces.
Without namespace, you are in global.
You can simply write:
Console.WriteLine(System.Math.Sqrt(4));
Or that in case of problem:
Console.WriteLine(global::System.Math.Sqrt(4));
You can also write:
using SystemMath = System.Math;
Console.WriteLine(SystemMath.Sqrt(4));
And since C# 6:
using static System.Math;
Console.WriteLine(Sqrt(4));
https://learn.microsoft.com/dotnet/csharp/language-reference/keywords/using-directive

Namespace and Assembly

I found something which gave me thinking.
I added using System.Windows; to my .cs file because I wanted tu use
DependencyObject foo
and the name was not recognized even when i change it on:
System.Windows.DependencyObject foo
To make first code work I had to add the assembly to my project.
So why we have using if we have to add assembly to project? I mean what is the mechanism behind that?
Using does not add the Assemblies for you. And you can only use the assemblies that are referenced in your project.
When you create a dot net project, if automatically add some assemblies for you, and if you need use any other assembly out of of them you need to add them. It is simply not feasible to add all the references in the world at first place.
Consider an analogy, You are a chef and you need to prepare some dish. You can only prepare dish using the items that are there in your kitchen, if you need some other ingredient which is not there, you get it from store and use it then. Imagine having all the ingredients of the world right in your kitchen!!
You must add the assembly to be able to use the classes inside of that assembly. Once you've added the assembly to your project, if you don't add the using statement, then you must always refer to the class in that assembly using the fully qualified name, e.g. System.Windows.DependencyObject. Once you add the using statement, you can refer to the class using just its class name, e.g. DependencyObject. In other words, the using statement is just there to provide a shorter way of refering to the class.
There are difference between those two.
Imagine you have the following code in File1.cs:
// File1.cs
using System;
namespace Outer.Inner
{
class Foo
{
static void Bar()
{
double d = Math.PI;
}
}
}
Now imagine that someone adds another file (File2.cs) to the project that looks like this:
// File2.cs
namespace Outer
{
class Math
{
}
}
The compiler searches Outer before looking at those using statements outside the namespace, so it finds Outer.Math instead of System.Math. Unfortunately (or perhaps fortunately?), Outer.Math has no PI member, so File1 is now broken.
This changes if you put the using inside your namespace declaration, as follows:
// File1b.cs
namespace Outer.Inner
{
using System;
class Foo
{
static void Bar()
{
double d = Math.PI;
}
}
}
Now the compiler searches System before searching Outer, finds System.Math, and all is well.
Some would argue that Math might be a bad name for a user-defined class, since there's already one in System; the point here is just that there is a difference, and it affects the maintainability of your code.
It's also interesting to note what happens if Foo is in namespace Outer, rather than Outer.Inner. In that case, adding Outer.Math in File2 breaks File1 regardless of where the using goes. This implies that the compiler searches the innermost enclosing namespace before it looks at any using statements.

'Class' is a namespace but is used like a 'type'

First, this is not the same as the many highly upvoted questions on this exact topic unless I'm missing one of them. All of them point that the issue is I have a namespace with the same name as the class. This is not the case (but it was).
I started out creating a new console application called BatchResizer and put a couple of classes there, but then decided to move this into a class library, called BatchResizer.Components; I then renamed the original console application to BatchResizer.ConsoleRunner, changed all classes in that project to namespace BatchResizer.ConsoleRunner.[...], set the assembly name and default namespace to the same.
There is a class titled BatchResizer but there are no namespaces titled [...].BatchResizer in the project anymore, but when I do var batchResizer = new BatchResizer() I get the error that the namespace is used like a class. There are items named like BatchResizer.ConsoleRunner.[...] or BatchResizer.Components.[...], but nothing ending in BatchResizer.
I've tried "cleaning" and rebulding the project, deleting the .suo file, deleting the /bin folder of all projects in the solution, and I've went through every class in all related projects for namespace collisions.
BatchResizer is still a namespace name, though. If it's also the same name as a class, you'll have to be more explicit:
var batchResizer = new Components.BatchResizer();
You could also add a using statement within your namespace:
namespace BatchResizer.ConsoleRunner
{
using Components;
internal class Program
{
private static void Main(string[] args)
{
var batchResizer = new BatchResizer();
}
}
}
If you want to get a bit geeky, then the C# 5.0 spec has this to say:
9.2 Namespace declarations
...The qualified-identifier of a namespace-declaration may be a single identifier or a sequence of identifiers separated by “.” tokens. The latter form permits a program to define a nested namespace without lexically nesting several namespace declarations. For example,
namespace N1.N2
{
class A {}
class B {}
}
is semantically equivalent to
namespace N1
{
namespace N2
{
class A {}
class B {}
}
}
So even if, as you say, no class is declared in the namespace BatchResizer, BatchResizer is declared as a namespace.
First, this is not the same as the many highly upvoted questions on this exact topic unless I'm missing one of them. All of them point that the issue is I have a namespace with the same name as the class. This is not the case (but it was).
BatchResizer may not be a 'final' namespace, but it' still a namespace
Namespace : Foo.BatchResizer.Components
Foo.BatchResizer.ConsoleRunner
Class : Foo.BatchResizer

Automatically added Using directive in C #

When using visual studio express to create a console C# application, I found that some namespaces are automatically added at the top of code at start:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
My understanding is first directive should allow me to use things defined in System and rest three directives are for namespaces which are defined within the overall System namespace which is already referred in first directive. Then why is VS 2013 adding rest of three using directives ?
You're misunderstanding how namespaces work.
For example, say I could define two classes, in two separate namespaces:
namespace MyNamespace
{
public class One
{
}
}
namespace MyNameSpace.SubNameSpace
{
public class Two
{
}
}
And then I want to create an instance of each in another class, like this:
var one = new One();
var two = new Two();
I'd have to include two using directives in order to do that.
using MyNamespace;
using MyNameSpace.SubNameSpace;
Including only the first using directive is not enough; it doesn't automatically include classes defined in the second namespace.
The using system does not automatically include everything within sub-namespaces. The first namespace (System) does NOT bring in the following three.
I think that the way to look at namespaces is that the "." is just another character in the name that makes it easier for humans to understand heirarchies of related namespaces and as far as Visual Studio is concerned, those are two distinct namespaces.
You can treat the like this
namespace System {
//... stuff
namespace Linq {
}
...
}
Namespace of System is different from namespace of System.linq. The first line will allow you to use System.Console. But the first line alone won't allow you to use methods in namespace System.Linq.

Categories