Reputation: 2473
I have a class that's name is the same as the namespace is is contained within:
Class File ReadModel.cs
namespace App.Core.ReadModel
{
public class ReadModel
{
}
}
Class File MyClass.cs
using App.Core.ReadModel; // this does not work
namespace Something
{
// using App.Core.ReadModel (Works if I un-comment)
public class MyClass
{
public void test()
{
var x = new ReadModel();
}
}
}
When trying to instantiate the class, even when trying to add a using directive at the top, the compiler is still unable to resolve the class. HOWEVER, if I put the using statements nested within the namespace, it works fine.
Can someone pls explain why this works? This is a new feature I've just discovered.
The error is: App.Core.ReadModel is a namespace but is used like a type
Upvotes: 1
Views: 1229
Reputation: 74345
The difference between
using System ;
using Foo.Bar ;
namespace My.Widget.Tools
{
public class MySpecialTool
{
...
}
}
and
using System ;
namespace My.Widget.Tools
{
using Foo.Bar ;
public class MySpecialTool
{
...
}
}
is that in the first case, the directive using Foo.Bar ;
causes the objects in the namespace Foo.Bar to be imported into the unnamed (global) namespace for the compilation unit. In the second case, the using directive
imports the objects in the namespace Foo.Bar into the namespace My.Widget.Tools.
The difference has to do with search order in resolving unqualified references.
Unqualified references are resolved by first searching within the enclosing named namespace. If the reference is not resolved, then the unnamed (global) namespace for the compilation unit is searched.
Consider the case where the above namespace Foo.Bar
contains a visible class that conflicts with a class contained in the System
namespace.
In the first case, where the Foo.Bar namespace has been loading into the global namespace, you'll get an error regarding an ambiguous reference if you try to reference the conflicting object: it will search the enclosing namespace first, on not finding it, it will then look into the global namespace and find multiple objects and whine.
In the second case, the enclosing namespace is searched first, on finding an object of the desired name, the unqualified reference is resolved and the compiler is happy: no conflict.
Note that you can coerce the search order to the global namespace by qualifying an object reference with the global:: prefix
. You can also define your own aliases with the using directive, either for a namespace:
using io = System.IO ;
or for a type:
using IntList = System.Collections.Generic.List<int> ;
the caveat with defining an alias for the namespace is that you then have to use the alias to resolve a reference. An alias defined for a type just gives you a [perhaps] shorthand way of naming the type. Probably more useful for generics than anything else. I don't see a lot of value in doing something like:
using Row = System.Data.DataRow ;
outside of writing obfuscated C#.
See also this question: Should 'using' statements be inside or outside the namespace?
§16 of ISO/IEC 23270:2006 (Information technology -- Programming languages -- C#) will tell you far more than you ever wanted to know about namespaces and using directives.
See also this MSDN piece on namespace aliases: http://msdn.microsoft.com/en-us/library/c3ay4x3d(v=vs.80).aspx
Upvotes: 3
Reputation: 18125
Edit again:
Nicholas answered your revised question very nicely. Please see his answer:
Visual Studio unable to resolve class name unless using nested using block
EDIT:
Using have to be at the top of the file. Move the using above the first namespace.
Example:
namespace App.Core.ReadModel
{
public class ReadModel
{
}
}
using App.Core.ReadModel; // cannot be placed here. Must be at top of file.
namespace App
{
public class Program
{
public static Main()
{
var obj = new ReadModel();
}
}
}
Original Answer (irrelevant to question):
Option 1: Rename Namespace
namespace App.Core.IO
{
public class ReadModel
{
}
}
Option 2: Use an Alias
using MyReadModel = App.Core.ReadModel.ReadModel;
public class Program
{
public static void Main()
{
var obj = new MyReadModel();
}
}
Option 3: Qualify Type Name
public class Program
{
public static void Main()
{
var obj = new App.Core.ReadModel.ReadModel();
}
}
Upvotes: 3