Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Namespace collisions

How is it possible that .NET is finding the wrong 'MyType' in this scenario?

I have a type A.B.C.D.MyType in a project that I'm working on, and I'm referencing a DLL that has a type A.B.MyType? I do not have any 'using A.B;' statements anywhere in my code, and I do have 'using A.B.C.D;'. When I compile, the compiler thinks any naked reference to 'MyType' means 'A.B.MyType'.

I know I could just rename the class or use an alias, but I'm wondering how this is even possible.

Any ideas?

Thanks!

like image 431
Chris Avatar asked Nov 04 '08 16:11

Chris


People also ask

What is name space collision in Java?

A naming collision is a circumstance where two or more identifiers in a given namespace or a given scope cannot be unambiguously resolved, and such unambiguous resolution is a requirement of the underlying system.

What is name collision in C++?

In computer programming, a name collision is the nomenclature problem that occurs when the same variable name is used for different things in two separate areas that are joined, merged, or otherwise go from occupying separate namespaces to sharing one.

What do you mean by namespace?

A namespace is a declarative region that provides a scope to the identifiers (the names of types, functions, variables, etc) inside it. Namespaces are used to organize code into logical groups and to prevent name collisions that can occur especially when your code base includes multiple libraries.

How do you avoid name collisions in C?

Most C code uses prefixes on functions and structs to avoid collisions, e.g sqlite3_exec() is a function belonging to SQLite3. The prefix stops the function colliding with exec() which is a standard POSIX function that got there first. So the prefix acts as a pseudo namespace.


2 Answers

Are you working in a namespace that is under A.B namespace? (for example A.B.X) if so the C# namespace resolutions (ECMA-334 C# Language Specification : 10.8 10.8 Namespace and type names) says:

... for each namespace N, starting with the namespace in which the namespace-or-typename occurs, continuing with each enclosing namespace (if any), and ending with the global namespace, the following steps are evaluated until an entity is located...

and then followed by:

If K is zero and the namespace declaration contains an extern-alias-directive or using-aliasdirective that associates the name I with an imported namespace or type, then the namespace-or-type-name refers to that namespace or type

This means that name resolution starts at the current namespace and searches all namespaces up to the root, and only after this hierarchical search ends, then the namespaces imported with the using clause are searched.

The following example prints "Ns1.Foo"

using Ns1.Foo.Foo2;

namespace Ns1.Foo
{
    class Foo
    {
        public void Print()
        {
            System.Console.WriteLine("Ns1.Foo");
        }
    }
}

namespace Ns1.Foo.Foo2
{
    class Foo
    {
        public void Print()
        {
            System.Console.WriteLine("Ns1.Foo.Foo2");
        }
    }
}

namespace Ns1.Foo.Bar
{
    class Bar
    {
        public void Print()
        {
            new Foo().Print();
        }

        static void Main()
        {
            new Bar().Print();
        }
    }
}

Edit: Adding a using clause inside a namespace, will make so that the namespace is searched before the hierarchical search of current namespace is done is done. Change the example to:

namespace Ns1.Foo.Bar
{
    using Ns1.Foo.Foo2;
    class Bar
    {
        public void Print()
        {
            new Foo().Print();
        }

        static void Main()
        {
            new Bar().Print();
        }
    }
}

and Ns1.Foo.Foo2 will be printed.

Edit: changed example

like image 167
Pop Catalin Avatar answered Oct 13 '22 09:10

Pop Catalin


Is your code in namespace A.B or A.B.C? If so, that's probably the issue. Use a using directive like this:

using TheTypeIWant = A.B.C.D.MyType;

then just refer to TheTypeIWant in your code.

EDIT: I've just tried the "using MyType=A.B.C.D.MyType" option, but that doesn't work. The above is fine though.

like image 37
Jon Skeet Avatar answered Oct 13 '22 10:10

Jon Skeet