6

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.

11
  • I remember reading somewhere that when searching for a name, it always starts from the current namespace. Commented Sep 14, 2020 at 6:12
  • 4
    "The behavior is as if parent namespaces are automatically referenced. Is this correct?" Yes. Commented Sep 14, 2020 at 6:13
  • 2
    or put using System; inside the namespace. If you want to know the gory details, 14.5.3 Using namespace directives in the ecma specs Commented Sep 14, 2020 at 6:18
  • 2
    Any reason why this would be "bad practice"? Partly because it makes the code slightly harder to review (vs being explicit about System). But honestly, it is going to be hard to review regardless due to the clash. Commented Sep 14, 2020 at 6:22
  • 2
    @GeorgeKerwood i was a bit optimistic with the reference to ecma, the resolution is actually spread out of several topics. There are 2 schools on whether you should use contained using, or global using in the compilation unit. There are benefits to both, I wouldn't consider either bad practice, as long as you were consistent. Commented Sep 14, 2020 at 6:34

1 Answer 1

7

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

Sign up to request clarification or add additional context in comments.

2 Comments

Thank you. I am aware of the solution options (aliases and fully qualified names). I was really asking to understand why parent namespaces were promoted above explicit references, or at least why no ambiguity error was thrown. I have my answer from the comments and your answer here will likely prove useful to someone.
Great, that's an answer now, thank you. Perhaps include the option of including the using statement within the namespace for completeness? As per @MichaelRandall comment.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.