This question already has answers here:
C#: Difference between using System.Text and System.Text.RegularExpressions
(3 answers)
Nested namespaces
(6 answers)
Using nested namespaces [duplicate]
(3 answers)
Closed 5 years ago.
I have run across something I find odd in C# .NET Core 2.0 and I am wondering what is going on here.
I have a file called FooBar.cs and it looks like this
namespace Foo
{
public class FooClass
{
}
namespace Bar
{
enum BarEnums
{
Bar1
,Bar2
,Bar3
}
}
}
And I have a simple program that looks like this
using System;
using Foo;
namespace Using
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hello World!");
FooClass fooClass = new FooClass();
Console.WriteLine(Bar.BarEnums.Bar1);
}
}
}
This gives me the following error:
Program.cs(16,22): error CS0103: The name 'Bar' does not exist in the current context
I am confused as to why the using statement exposes the class within the name space but it does not expose the namespace also found at the same level? If I put in using Foo.Bar it still gives the same error.. so the using statement can see the namespace but it does not help it find the references below.
Now if I put in Foo.Bar.BarEnums.Bar1 it will work just fine.. But why do I not have to put in Foo.FooClass following the same nomenclature as with the reference to the enums? Is this just a difference between accessing enums vs classes from within a namespace?
That happens because using Foo only imports the types contained in the given namespace, but it does not specifically import the nested namespaces. So that´s why when you reference your enum you have to do it with the full namespace reference.
This is a C# language specification.
Here is an explanation from a guy from the C# team:
In C#, when you specify a “using” clause, such as
using System.Text;
the compiler only imports the types in System.Text into the global
namespace – it doesn’t do the same with any namespaces inside of
System.Text. So, while that using allows me to write:
StringBuilder s = new StringBuilder();
it does not allow me to write:
RegularExpressions.Regex r = new RegularExpressions.Regex();
Why?
Well, an early version of the C# compiler had that behavior, but we
found that it had a few issues:
First, it made the code harder to follow. In the above example,
RegularExpressions.Regex() could be a global name, or a name based on
any of my using clauses. Having to look at the top of your code to
figure out what a name is is something we’d like to avoid.
The second problem had to do with collisions between namespace names,
which occurred much more often with this behavior. If there was
another namespace with a RegularExpressions namespace inside of it,
the user wouldn’t be able to have a “using” statement for both – even
if they didn’t actually care about that namespace.
We therefore decided to change the behavior.
https://blogs.msdn.microsoft.com/csharpfaq/2004/03/07/why-dont-namespace-using-directives-import-nested-namespaces/
And here is the C# spec: https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/namespaces
Related
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
This question already has answers here:
.NET - Multiple libraries with the same namespace - referencing
(5 answers)
Closed 3 years ago.
THAT'S NOT A DUPLICATE It doesn't work with an alias
How can I reference an assembly with the same Namespace?
This is DLL1:
namespace ClassLibrary1
{
public class Class1
{
public void Test()
{
Console.WriteLine("Test 1");
}
}
}
And this is DLL2 that references DLL1:
namespace ClassLibrary1
{
public class Class1
{
public void Test()
{
new ClassLibrary1.Class1().Test(); //Should call Test() in DLL1
Console.WriteLine("Test 2");
}
}
}
Obviously this will not work as expected. I already tried to set a different alias for the reference (DLL2 -> DLL1). Visual Studio seems to ignore the alias not matter what I do.
It doesn't work with an alias
myAlias::ClassLibrary1.Class1() is NOT WORKING Visual Studio (the compiler) ignores the alias. If I build and start my solution I get an endless loop.
You need to specify the alias explicitly when refering to the type, e.g. new myAlias::ClassLibrary1.Class1(). You can also use a using alias to do something like using AnotherClass1 = myAlias::ClassLibrary1.Class1; for convenience.
Of course, if possible, you want to avoid having this problem in the first place. Choose namespace and type names to avoid collisions, if you have control over either assembly.
begginers question about C#.
In every program I have to include several namespaces, like:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
Why do I have to include:
using System.Collections.Generic;
using System.Linq;
using System.Text;
... since they are included with first one:
using System;
Thank you in advance!
Because nested namespaces are not included with parent one. See using directive documentation for details
A using directive does not give you access to any namespaces that are nested in the namespace you specify.
System and System.IO namespaces are different.
You can treat "subnamespace" as parent-child relationship in the object model. If you have access to the "Car" object does not mean that you have access to car's wheels.
System is a huge namespace that contains hundreds of nested namespace and thousands of classes. You should specify all nested namespaces separately to state what part of the module are you interested in.
Imagine these namespaces with these classes (the last name is a class):
A.B.Class1
A.Class2
Now you have the following:
using A - allows you to refer to Class2 directly... but not to Class1.
using A.B - allows you to refer to Class1 directly but not to Class2.
If you want to refer to both classes directly in your code, you need both usings.
System and System.Text are two different namespaces. That System.Text seems to be a part of System is the semantics we as programmer put into it. There's no such thing as a nested namespace from a platform view;
But even if that was not the case what should happen if you had
namespace MySystem{
namespace Foo{
class Bar {...}
}
class Bar{...}
}
using MySystem;
class MyClass{
private Bar _myBar; //Which one is it MySystem.Foo.Bar or MySystem.Bar?
}
Since you're beginner let me clarify one thing namespace in C# and package in Java are different things. no need to merge them.
Not all classes in .net is inside one big container.Doing so increases the chance of class name collision and it doesn't look good in the first place.Namespaces are containers that try to keep your library clean and make more sense.Having a FTP class and String class together under one container does not logically make any sense.They do two different things and they should be kept in separate containers.
Also a namespace can be nested.Sometime A namespace can all but have just another namespace,without any class.so to access a class you need to qualify the full namespace before you can use it.
In your case you use different classes ,which are on different containers.So if you need them you need to qualify them with their namespace.
Just an added example to make you understand clearly.
A child Namespace cant be accessed by calling parent namespaces
Namespace Main //only code and classes are accessible
{
//code for Main Namespace
Namespace subMain //only code and classes are accessible
{
//code for subMain
Namespace verySubMain //only code and classes are accessible
{
//code for verySubMain
}
Namespace otherVerySubMain //only code and classes are accessible
{
//code for otherVerySubMain
}
}
}
If you wanted access to a class in System.Text without the using statement, you would have to Text."Name of class/function" every time you wished to use it.
This way you can just call "name of class/function".
Not sure if you are a beginner, but that's the simplest way I can describe put it.
I have the following two files:
IGlobalApiProvider.cs
using System.Collections.Generic;
using Vert.Slack;
namespace Vert.Interfaces
{
public interface IGlobalApiProvider
{
List<Im> ImList();
}
}
And the corresponding implementation: SlackApi.cs
using System.Collections.Generic;
using Vert.Interfaces;
namespace Vert.Slack
{
public class SlackApi : IGlobalApiProvider
{
public List<Im> ImList()
{
...
}
}
}
Now, Intellisense is telling me that when I use IM in IGlobalApiProvider it's resolving to Im, which is defined in a file named RtmStart.cs which has no namespace declaration. When I use IM in SlackApi.cs, it's resolving to Vert.Slack.Im which is defined in the Vert.Slack namespace in a file named Im.cs. The weird behavior alerted me to the redundant definition, so I removed it and things are working fine.
However, I'm confused about why Visual Studio behaved differently in these two ways. I can tell something was scanning for the class names in a different pattern in the two situations. I can also tell that being used in the same namespace vs being used in a class that uses the namespace seems to be the trigger. What I don't know is what mechanism controls the logic behind this behavior.
Can anyone shed light on this?
Everything you see is contained in Vert.dll, which consists of one project, Vert.csproj
Link to the four files mentioned in this post as they existed at the time of writing.
This has to do with the difference between the global and Vert.Slack namespaces.
The compiler looks for the most explicit namespace with the proper class defined.
In this example, when the compiler looks for the definition of Im in IGlobalInterfaceProvider.cs, there is no namespace defined (or used) in this file that contains the class, but Im is also defined in this file - which is declared in the global namespace.
When the compiler looks for the definition of Im in SlackApi.cs, Im is found in the explicit Vert.Slack namespace, and utilizes that class.
The answer here is a similar topic and may provide more insight.
This may be related to the fact that your namespaces are in the wrong place ;-)
http://www.stylecop.com/docs/SA1200.html
This answer here gives a good explanation: Should 'using' statements be inside or outside the namespace?
This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
Should Usings be inside or outside the namespace
I am looking at a code base where the author (one I respect) consistently places using statements inside of the namespace, as opposed to above it. Is there some advantage (more efficient GC?) to doing so or is this just a code style preference?
Cheers,
Berryl
Never put them inside without using "global::" or your code will become brittle.
namspace bar {
using foo //this may mean "using global::bar.foo OR using global::foo"
}
Reference
http://blogs.msdn.com/b/ericlippert/archive/2007/06/25/inside-or-outside.aspx?wa=wsignin1.0
If you have multiple namespaces in the same file then you will be scoping usings only to the containing namespace instead of to all namespace in the entire file.
Also see (just found this good explanation) Should 'using' statements be inside or outside the namespace?
Scott Hanselman did a post about this back in July 2008. I don't know if this changed with the .NET 4 framework, but it basically came down to being a preference issue unless you're naming your classes the same as existing classes as well as multiple namespaces in a single file.
It's a preference thing but there is a semantic difference when you use the statement on the inside versus on the outside in some scenarios.
using Bar;
namespace Foo
{
using Bar;
namespace Bar
{
class C
{
}
}
namespace Baz
{
class D
{
C c = new C();
}
}
}
namespace Bar
{
class E
{
}
}
In this, the outer using statement refers to the namespace Bar that is after namespace Foo. The inner using statement refers to Bar that is inside Foo. If there were no Bar inside Foo, then the inner would also refer to the outer Bar.
Edit And as Jonathan points out, the inner using can be changed to `using global::Bar;" to refer to the out Bar namespace, which would happen to break this particular code because of D trying to use C.
It's MS recommend practice. Programs such as stylecop recommend it.
Check out Is sa1200 All using directives must be placed inside the namespace (StyleCop) purely cosmetic? for a more in-depth discussion