Companyname.Foo' Is a 'Namespace' But Is Used Like a 'Type'

CompanyName.Foo' is a 'namespace' but is used like a 'type'

how do I tag Eric Lippert?

If you have something you want brought to my attention you can use the "contact" link on my blog.

I'm still utterly confused why the C# compiler bothers to check for collisions between namespaces and types in contexts where it makes no sense for a namespace to exist.

Indeed, the rules here are tricky. Coincidentally, two weeks ago I wrote and posted a series of blog articles about some of these issues closely related to this very issue; they'll actually go live in early March. Watch the blog for details.

UPDATE: The articles mentioned above are here:

Link

Why does this error occur?

Let me rephrase the question into several questions.

What sections of the specification justify the production of this error?

I think that's already been covered satisfactorily in other answers. The type resolution algorithm is extremely well-specified. But just to sum up: being inside something of the right name "binds more tightly" than using something of the right name from the outside. When you say:

using XYZ;
namespace ABC.DEF
{
class GHI : DEF { }
}

that is the same as

using XYZ;
namespace ABC
{
namespace DEF
{
class GHI : DEF { }
}
}

So now we must determine the meaning of DEF. We go from inside to outside. Is there a type parameter of GHI called DEF? No. Look at the container. Is there a member of DEF called DEF? No. Look at the container. Is there a member of ABC called DEF? YES. We're done; we have determined the meaning of DEF, it is a namespace. We discover the meaning of DEF before we ask "does XYZ have a member DEF?"

What design principles influence this design?

One design principle is "names mean the same thing no matter how you use them". The language does not 100% obey this principle; there are situations in which the same name can be used to refer to two different things in the same code. But in general, we strive for a situation where when you see "Foo" two times in the same context, it means the same thing. (See my article on The Color Color Problem for some details on this, as well as my articles on identifying violations of the "simple name" rules.)

One design principle is "no backtracking". We do not ever say in C# "I see that you used a name to refer to something that is not legal to refer to in this context. Let me abandon the result of name binding and start over, looking for something that might work."

A larger principle that underlies the "no backtracking" principle is that C# is not a "guess what the user meant" language. You wrote a program where the best possible binding of an identifier identified a namespace when a type was expected. There are two possibilities. Possibility one: you've made an error that you want to be told about so that you can take action to correct it. Possibility two: you meant for a less-good binding to be the one we choose, and so we should guess from amongst all the possible less-good bindings to figure out which one you probably meant.

That's a good design principle in languages like JScript -- JScript is all about muddling on through when the developer does something crazy. C# is not that kind of language; the feedback we get loud and clear from our developers is tell me when something is broken so I can fix it.

The thing about "no backtracking" is that it makes the language much easier to understand. Suppose you have something like this mess:

namespace XYZ.DEF
{
public class GHI {}
}
namespace QRS.DEF.GHI
{
public class JKL { }
}
...
using QRS;
namespace TUV
{
using XYZ;
namespace ABC
{
namespace DEF
{
class GHI { }
class MNO : DEF.GHI.JKL { }
}
}
}

Work out the base type of MNO. With no backtracking we say "DEF is ABC.DEF". Therefore GHI is ABC.DEF.GHI. Therefore JKL is ABC.DEF.GHI.JKL, which does not exist, error. You must fix the error by giving a type name that lets the compiler identify which DEF you meant.

If we had backtracking, what would we have to do? We get that error, and then we backtrack. Does XYZ contain a DEF? Yes. Does it contain a GHI? Yes. Does it contain a JKL? No. Backtrack again. Does QRS contain an DEF.GHI.JKL? Yes.

That works, but can we logically conclude from the fact that it works that it is the one the user meant?

Who the heck knows in this crazy siutation? We got all kinds of good bindings in there that then went bad very late in the game. The idea that we stumbled upon the desired answer after going down many blind alleys seems highly suspect.

The correct thing to do here is not to backtrack multiple times and try out all kinds of worse bindings for every stage of the lookup. The correct thing to do is to say "buddy, the best possible match for this lookup gives nonsensical results; give me something less ambiguous to work with here please."

An unfortunate fact about writing a language where the compiler by design complains loudly if the best match is something that doesn't work, is that developers frequently say "well, sure, in general I want the compiler to point out all my mistakes -- or, rather, all my coworker's mistakes. But for this specific case, I know what I am doing, so please, compiler, do what I mean, not what I say."

Trouble is, you can't have it both ways. You can't have both a compiler that both enforces rigid rules that make it highly likely that suspicious code will be aggressively identified as erroneous and allow crazy code via compiler heuristics that figure out "what I really meant" when you write something that the compiler quite rightly sees as ambiguous or wrong.

For an object lesson in how lots of pro devs vehemently dislike the effects of a language design that aggressively identifies errors rather than guessing that the developer meant for the worse result to be chosen, see the 116 comments to this article on a minor and rather unimportant aspect of overload resolution:

(Note that I am no longer responding to comments on this issue; I've explained my position over ten times. If all those explanations are not convincing, that's because I'm not a very good convincer.)

And finally, if you really want to test your understanding of how the name resolution rules work in C#, try out this little puzzle. Almost everyone gets it wrong, or gets it right for the wrong reasons. The answer is here.

namespace' but is used like a 'type'

I suspect you've got the same problem at least twice.

Here:

namespace TimeTest
{
class TimeTest
{
}

... you're declaring a type with the same name as the namespace it's in. Don't do that.

Now you apparently have the same problem with Time2. I suspect if you add:

using Time2;

to your list of using directives, your code will compile. But please, please, please fix the bigger problem: the problematic choice of names. (Follow the link above to find out more details of why it's a bad idea.)

(Additionally, unless you're really interested in writing time-based types, I'd advise you not to do so... and I say that as someone who does do exactly that. Use the built-in capabilities, or a third party library such as, um, mine. Working with dates and times correctly is surprisingly hairy. :)

How to fix 'Attribute is a namespace but is used like a type' error in C#

You are defining your classes in the namespace named Attribute.

Try one of the following:

  1. Change your namespace name to something else.

  2. Inherit from System.Attribute.

Student' is a namespace but is used like a type error while declaring DbSet inside DbContext

Sounds like you have a namespace and a class that is named Student. Not very good. To get around it you can prefix the class name with the namespace; like Student.Student. But the best idea it to rename the namespace I would say!

https://blogs.msdn.microsoft.com/ericlippert/2010/03/09/do-not-name-a-class-the-same-as-its-namespace-part-one/

Namespace set as Used because of One Type Inside being Used?

As suggested by immbis in the comment, this is defined by the standard:

3.4.2: Argument dependent name lookup

  1. When the postfix-expression in a function call is an unqualified-id, other namespaces not considered during the usual
    unqualified lookup may be searched, and in those namespaces,
    namespace-scope friend function or function template declarations not
    otherwise visible may be found. These modifications to the search
    depend on the types of the arguments (and for template template
    arguments, the namespace of the template argument).

    ...

If you want to defeat this mecanism, you have to use nested namespace like this, but it's tricky:

namespace Test
{
struct Magic
{
int poof;
};
struct Magic2
{
int poof;
};

namespace Test2 { // use a nested namespace that will not be searched autoamtically
int Alakazam(const Magic& m)
{
return m.poof;
}

int Alakazam(const Magic2& m)
{
return m.poof;
}
}
using namespace Test2; // but give some access to the enclosing namespace
};

Live Demo : Then, your two first calls will not be valid any longer. However, the last call in your example is still possible: you can't prevent the use of fully qualified names outside of the namespace.

Why is the compiler conflicting with a namespace in inheritance

The compiler doesn't care much about if your reference is a class or a namespace when it first resolves names. If a name isn't fully qualified, it will always try to find it in the local namespace first - including the namespace name itself. If it can't find it in the local namespace it will try the using directives.

The reason it resolves it like that is, that you can after all create a namespace hierarchy and all classes and namespaces are separated by .. Thus while resolving names, the compiler doesn't care much about the type but only about the hierarchy path. It will care about the type though as soon as it has found a match. In this case it is a namespace when it expects a class and thus fails.

With sub-namespaces and sub-classes it'd be hard for the compiler to identify a match if it simply tries to fit one and it might find multiple references if it just matches random namespaces in the same assembly. Thus it's always local namespace first, then moves up the hierarchy through to other assemblies. If it's not clear because two sub-namespaces or classes with the same name exist in different namespaces that are both referenced, you have to be even more clear.

Error is property but is used like type

Constructors do not have a return type. Change your code to this:

using System.ComponentModel.DataAnnotations;
namespace Model
{
public class NewUser
{
public string Password { get; set; }
public NewUser()
{
Password = "Admin123";
}
}
}

When you define a constructor, you just declare the visibility (public, protected, or private) and then the name of the class (NewUser in this case), then optional parameters. In your case, you don't look like you want any. But you could do this too:

public NewUser(string password)
{
Password = password;
}

Then instantiate it like this:

var newUser = new NewUser("Admin123");

And its okay to have both constructors, if you want. That way they can implicitly specify a password, or if they don't specify one, default it to something (such as Admin123)

field' but is used like a 'type'

You can't call a method on a field outside of a method:

using System;
using PaymentPlanLogic;
namespace PaymentPlanStoreLogic
{
public class Class1
{
Logger myLog = new Logger();

void YouForgotThisMethod()
{
myLog.createLog();
}
}
}

C# error when class shares name with namespace

Eric Lippert's blog posts (parts one; two; three; four) give good insight into this. From part one:

This reveals an interesting point about the design of the “type binding” algorithm in C#. That is, the algorithm which determines what type or namespace a name like “X.Y” is talking about. We do not “backtrack”. We do not say “well, suppose X means this. Then Y would have no meaning. Let’s backtrack; suppose X means this other thing, oh, yes, then Y has a meaning.” We figure out what X unambiguously means, and only then do we figure out what Y means. If X is ambiguous, we don’t check all the possibilities to see if any of them has a Y, we just give up.

Here we've only actually got an X, but I think the compiler tries to work out whether that means it's a namespace or a type before checking whether or not there's anything else after it.

Personally, I don't mind this restriction. It means you're discouraged from writing code with a namespace and class called the same thing - and as that's a confusing situation from a human point of view, I'm happy for it to be discouraged.



Related Topics



Leave a reply



Submit