Namespace access issue with sub namespaces - c#

I have two classes in the different sub namespaces:
namespace Acme.ByteTools
{
class ByteTools
{
...
}
}
namespace Acme.IO
{
class Reader
{
...
}
}
While I trying to access Acme.ByteTools from the any third namespace, I use:
using Acme.ByteTools;
...
ByteTools.BytesToUint(...);
but when I try to access Acme.ByteTools from Acme.IO, compiler require different notation:
using Acme.ByteTools;
...
ByteTools.ByteTools.BytesToUint(...);
Why?

As others including the legendary Eric Lippert have stated...please don't create collisions. I've seen code riddled with using alias directives because of collisions and I simply cannot express how frustrating it is to see a namespace change its name from class to class.
The confusion speaks for itself. Just look at something like this:
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
A a = new A();//A's a namespace
A.A b = new A.A();//A is a namespace this works!
global::A.A nuts = new A();//This fails...ugh
Console.ReadLine();
}
}
}
namespace A
{
class A
{
public void DoWork()
{
A a = new A();//A's a class
A.A b = new A.A();//A is a type (class) A.A makes no sense to the compiler
global::A.A nuts = new A();//Oh but this works fine
}
}
}
So the fix is make sure the namespaces and classes are different. A using alias directive using B = A; might ease the pain however that directive can change from file to file and anything to its right must be fully qualified.

Related

Does inheritance also automatically "inherit" namespaces from its parent?

Just wanted to ask generic question about Namespaces. If class A inherits class B and doesn't explicitly reference (using) B's namespace, do I have to explicitly using B namespace in my calling code to call B's methods from an instance of A? Is this language dependent (C#, C++)?
Ex in C#:
// Namespace X
class A : B
{
public void methodA(){...}
}
// Namespace Y
class B
{
public void methodB(){...}
}
In other code using A:
using X;
// do I need using Y?
...
A obj = new A();
obj.methodB(); // calls methodB() using instance of A
...
if A is in namespace X and B in Y, you can't do
// Namespace X
class A : B
{
...
};
you need to do:
class A : Y::B
{
...
};
So you see you had to inherit B using the qualification and there's nothing special going on there. This is in C++ btw.
If A needs anything more from Y it'll need to similarly qualify it.
Anybody using A needs to qualify it with X::A or import everything or just A, depending, to use it - using X::A; or using namespace X;. That has no effect on what happens to the visibility of things inside Y though.
The only thing that might surprise you is Koenig Lookup, so maybe read that.
No namespaces are not inherited by classes in C++ (and in C#). However due to the ADL (Argument Dependent Lookup) you can "inherit" some names from the namespace of a base class.
Here is a demonstrative program
#include <iostream>
namespace N1
{
struct A {};
void f( const A & )
{
std::cout << "N1::f( const A & )\n" << '\n';
}
}
namespace N2
{
struct B : N1::A
{
B() { f( *this ); }
};
}
int main()
{
N2::B b;
return 0;
}
Its output is
N1::f( const A & )
To "inherit" a namespace you can use the using directive in a namespace or in a block scope. For example
namespace N1
{
struct A {};
}
namespace N2
{
using namespace N1;
struct B : A
{
};
}
Take into account that you may not use the using directive in a class scope.
Or you can introduce only some names by means of a using declaration.
Classes do not inherit namespaces. using only imports the symbols in a namespace into the current source file. It has no effect on your classes themselves.
This C# code:
using System;
public class A {
public void Run() {
Console.WriteLine("Foobar");
}
}
Is completely equivalent in its effects, both in the CIL emitted as well as how users of A will use the class or derive it, to this code:
public class A {
public void Run() {
System.Console.WriteLine("Foobar");
}
}
Let's say that we import a type that we return from a method:
using System.IO;
public class A {
public Stream createStream() {
// implementation irrelevant
}
}
If we then declare class B : A in another source file, the createStream() method is inherited, and it still returns System.IO.Stream, even if the source file B is declared in doesn't have using System.IO, and users of class B do not need to import System.IO in order to use the stream returned by createStream(); the system knows the fully-qualified type is System.IO.Stream.
public class B : A {
public void doSomethingWithStream() {
// We can use a System.IO.Stream object without importing System.IO
using (var s = createStream()) {
}
}
}
public class C {
public static void doSomethingElseWithStream(B b) {
// As can other stuff that uses B.
using (var s = b.createStream()) {
}
}
}
No, there is no such thing as a inherited namespace.
Namespace does not have anything that can be derived/inherited.
If you want to inherit a class A that is in different namespace, you need to add "using namespace ..."

Why can't i use partly qualified namespaces during object initialization?

I suspect this is a question which has been asked many times before but i haven't found one.
I normally use fully qualified namespaces if i don't use that type often in the file or i add using namaspacename at the top of the file to be able to write new ClassName().
But what if only a part of the full namespace was added ? Why can't the compiler find the type and throws an error?
Consider following class in a nested namespace:
namespace ns_1
{
namespace ns_1_1
{
public class Foo { }
}
}
So if i now want to initialize an instance of this class, it works in following ways:
using ns_1.ns_1_1;
public class Program
{
public Program()
{
// works, fully qualified namespace:
var foo = new ns_1.ns_1_1.Foo();
// works, because of using ns_1.ns_1_1:
foo = new Foo();
}
}
But following doesn't work:
using ns_1;
public class Program
{
public Program()
{
// doesn't work even if using ns_1 was added
var no_foo = new ns_1_1.Foo();
}
}
it throws the compiler error:
The type or namespace name 'ns_1_1' could not be found (are you
missing a using directive or an assembly reference?)
I assume because ns_1_1 is treated like a class which contains another class Foo instead of a namespace, is this correct?
I haven't found the language specification, where is this documented? Why is the compiler not smart enough to check if there's a class or namespace(-part)?
Here's another - less abstract - example of what i mean:
using System.Data;
public class Program
{
public Program()
{
using (var con = new SqlClient.SqlConnection("...")) // doesn't work
{
//...
}
}
}
Edit: now i know why this seems very strange to me. It works without a problem in VB.NET:
Imports System.Data
Public Class Program
Public Sub New()
Using con = New SqlClient.SqlConnection("...") ' no problem
End Using
End Sub
End Class
This obvious way unfortunately not working but you can make all this by an alias namespace:
using ns_1_1 = ns_1.ns_1_1;
public class Program
{
public Program()
{
var no_foo = new ns_1_1.Foo();
}
}
The documentation says:
Create a using directive to use the types in a namespace without having to specify the namespace. A using directive does not give you access to any namespaces that are nested in the namespace you specify.
So the using only includes the types (not the namespaces) that are defined in the specified namespace. In order to access types of nested namespace you need to specify it explicitly with a using directive as you did in your first example.
This is documented in the standard in 3.8 Namespace and Type Names, but it's a bit convoluted to follow.
The gist of it that a partial namespace reference is only looked for in the namespace where it occurs, and each layer outwards. using-directives are not checked.
In your example, ns_1_1.Foo would be found if Foo is found anywhere in:
Program.Program.ns_1_1.Foo
Program.ns_1_1.Foo
ns_1_1.Foo
Partial namespaces will work only if your current class is part of that partial namespace. Using statements are not considered for accessing types through partial namespace.
For instance this will work because your current namespace is ns_1
namespace ns_1
{
public class Program
{
public Program()
{
var no_foo = new ns_1_1.Foo();
}
}
}

Why do I need fully qualified name to access static property of a class that was included with "using"

If I have this class declaration
namespace DatabaseCache
{
public class DatabaseCache
{
public static bool somePublicFlag ;
}
}
In another class I have this statement
using DatabaseCache;
Why do i need to write a statement like this in that class
DatabaseCache.DatabaseCache.somePublicFlag = true ;
instead of just
DatabaseCache.somePublicFlag = true ;
You don't need that if you don't have a Namespace and Type name collision. A well designed library will not have such collision, So design your library accordingly to avoid such collision.
namespace DatabaseCache
{
//change the name of the class
public class DifferentNameThanNamespace
{
public static bool somePublicFlag ;
}
}
Because the compiler doesn't know if DatabaseCache is referring to the namespace or the class. Even thought you're using the namespace it's still perfectly legal to preface types within that namespace by the namespace, so the call is ambiguous.
You could alias the type by using:
using DC = DatabaseCache.DatabaseCache;
and then just calling
DC.somePublicFlag
but that's just masking the problem - renaming the namespace is a better solution.
In order to avoid ambiguities, it is not recommanded to declare a class with the same same as its namespace.
The Framework Design Guidelines say in section 3.4 “do not use the same name for a namespace.
To learn about how to activate/disable this kind of warning see this link
(Of course the advice is to not use the same name for two distinct things.)
Answer with an extension. Suppose you have one file with:
namespace DatabaseCache
{
public class DatabaseCache // same name as namespace :-(
{
public static bool somePublicFlag;
}
public class somePublicFlag // evil other type
{
}
}
Then now it depends on where you put your using directives relative to your namespace. For example, in another file, this will be legal:
namespace Other
{
using DatabaseCache;
class DbcTestClass1
{
void M()
{
DatabaseCache.somePublicFlag = true; // legal!
}
}
}
In the above example, somePublicFlag refers to the field of the class!
However, this is legal as well:
using DatabaseCache;
namespace Other
{
class DbcTestClass2
{
void M()
{
var instance = new DatabaseCache.somePublicFlag(); // legal!
}
}
}
With that placing of the using directive, the somePublicFlag refers to the "evil" class of that name. The qualifier DatabaseCache. in this case is redundant, but it is still seen as a reference to the namespace global::DatabaseCache because the global namespace (null namespace) is searched first in this case.
To learn more, see my answer elsewhere. It all depends on the order in which the different namespaces (including the global namespace) are searched for a matching name.

Why do extension methods not work with namespace aliasing?

This may be an ignorant question, but I'm unsure why I can not use namespace aliasing and extension methods together.
The following example works just fine:
Program.cs
using System;
using ExtensionMethodTest.Domain;
namespace ExtensionMethodTest
{
class Program
{
static void Main(string[] args)
{
var m = new Domain.MyClass();
var result = m.UpperCaseName();
}
}
}
MyClass.cs
using System;
namespace ExtensionMethodTest.Domain
{
public class MyClass
{
public string Name { get; set; }
}
}
MyClassExtensions.cs
using System;
namespace ExtensionMethodTest.Domain
{
public static class MyClassExtensions
{
public static string UpperCaseName (this MyClass myClass)
{
return myClass.Name.ToUpper();
}
}
}
However, when I alias domain as follows in Program.cs:
using Domain = ExtensionMethodTest.Domain;
The extension method no longer works..
This can be rather frustrating when I'm dealing with converting various domain objects to contract objects (let's say I have 4 domain assemblies and 4 contract assemblies) for use in a web service. Using aliasing would be very handy as I could alias as follows and continue to use the various extension methods (such as ToContract, etc.):
using BillingContracts = Namespace.Billing.Contracts;
using IssuingContracts = Namespace.Issuing.Contracts;
etc...
I look forward to the answer.. I'm sure it's straight forward, but I, for the life of me, can't figure out why it doesn't work.
Thanks!
Make sure to still add a non-aliased using statement:
Program.cs
using System;
using ExtensionMethodTest.Domain; //DON'T FORGET A NON-ALIASED USING
using MyDomain = ExtensionMethodTest.Domain;
namespace ExtensionMethodTest
{
class Program
{
static void Main(string[] args)
{
var m = new MyDomain.MyClass();
var result = m.UpperCaseName();
}
}
}
MyClass.cs
using System;
namespace ExtensionMethodTest.Domain
{
public class MyClass
{
public string Name { get; set; }
}
}
MyClassExtensions.cs
using System;
namespace ExtensionMethodTest.Domain
{
public static class MyClassExtensions
{
public static string UpperCaseName (this MyClass myClass)
{
return myClass.Name.ToUpper();
}
}
}
I also love to use namespace aliasing but its not working in case of Extension methods. So one thing that i did is, I changed the namespace of extension class to same namespace that my main project has (although my extension class resides in sub folder of main project).
Suppose I have a project myFirstProj which surely has namespace myFirstProj for root classes. My extension class is present in myFirstProj/Common/myExtensionClass with contains namespace myFirstProj.Common { //myExtensionClass }.
So now what I did is, I changed the namespace of myExtensionClass from namespace myFirstProj.Common{ //myExtensionClass } to namespace myFirstProj{ //myExtensionClass } .
Now i can use my extension methods in my whole project myFirstProj event without specifying using statement for my extension class.
I know this isn't a standard way to that but I haven't found any other workaround for it expect this one because for my Project there is a requirement to go with namespace aliasing for project namespaces.

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!
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
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.
Just a guess: in your project properties, is the "default namespace" set to A.B ?

Categories