views:

146

answers:

6

In the Java and Python world, you look at a source file and know where all the imports come from (i.e. you know in which file the imported classes are defined). For example:

In Java:

import javafoo.Bar;

public class MyClass {
    private Bar myBar = new Bar();
}

You immediately see that the Bar-class is imported from javafoo. So, Bar is declared in /javafoo/Bar.java

In Python

import pythonbaz
from pythonfoo import Bar

my_bar = Bar()
my_other = pythonbaz.Other()

Here, it is clear that Bar comes from the pythonfoo package and Other is obviously from pythonbaz.

In C# (correct me if I'm wrong):

using foo
using baz
using anothernamespace
...

public class MyClass
{
    private Bar myBar = new Bar();
}

Two questions:
1) How do I know where the Bar-class is declared? Does it come from the namespace foo, or bar, or anothernamespace? (edit: without using Visual Studio)

2) In Java, the package names correspond to directory names (or, it is a very strong convention). Thus, when you see which package a class comes from, you know its directory in the file system.

In C#, there does not seem to be such a convention for namespaces, or am I missing something? So, how do I know which directory and file to look in (without Visual Studio)? (after figuring out which namespace the class came from).

Edit clarification: I am aware that Python and/or Java allow wildcard imports, but the 'culture' in those languages frowns upon them (at least in Python, in Java I'm not sure). Also, in Java IDEs usually help you create minimal imports (as Mchl. commented below)

+1  A: 

Usually, the tooltip when you mouse-over the type name reveals some extra information. Else you could always right-click the type name, and 'Go to definition'.

Joachim VR
I think it is the best answer. I don't care where the code is as long as VS and complier knows that :-) If you want some order, C# allows you to make it by yourself.
Bart
+2  A: 

How do I know where the Bar-class is declared? Does it come from the namespace foo, or bar, or anothernamespace? Visual Studio allows me to jump there, of course, but what if I am just taking a quick look at a source file in my editor?

Essentially, you don't - but IntelliSense is helping. You cannot actually be sure by just taking a quick glance at the code, but you can hover over the symbol with your cursor, for example. But this is also possible in Python:

from foobar import *
from bazbaz import *

a_bar = Bar()

Where does Bar come from now?

In C#, there does not seem to be such a convention for namespaces, or am I missing something? So, how do I know which directory and file to look in? (after figuring out which namespace the class came from).

No, assemblies do not correspond to directory structures, which, IMHO, is a good thing. The solution explorer is offering a view of all the references added to your project. These references being assemblies, have a concrete representation as a PE file somewhere on your machine. You can easily look at the properties of a reference to see where the physical file is located.

Edit: In order not to contradict other answers in this thread and create confusion: What I mean by saying assembly names do not correspond to directory names is that it is not actually enforced.

Jim Brissom
You are right about the python imports, but that's why the `import *` is usually strongly discouraged in python.
Martin S.
But aren’t wildcard imports frowned upon in Python – for this very reason?
Konrad Rudolph
Exactly - but the point of the question is not about coding style, but the assumption that Python and/or Java somehow prevent what Martin believes to be a weakness/annoyance of C# compared to those languages, which obviously isn't true. As for me, I would seriously advise against using import statement like these.
Jim Brissom
I'm sorry, but that was in fact the point of the question. Python and/or Java do not prevent it directly, but the culture encourages good structure and frowns upon wildcard imports (at least in Python, in Java I'm not sure). I should have worded better.
Martin S.
+2  A: 

In C#, there does not seem to be such a convention for namespaces, or am I missing something?

I don’t know about other projects but I’m pretty sure that in every .NET project I have worked on, we used this convention, i.e. namespaces always corresponded to folder names (except for the outermost namespace(s) which correspond to the assembly from which the namespace comes).

Konrad Rudolph
+5  A: 

1) Well, you can do the same thing in Java too:

import java.util.*;
import java.io.*;

...

InputStream x = ...;

Does InputStream come from java.util or java.io? Of course, you can choose not to use that feature.

Now, in theory I realise this means when you're looking with a text editor, you can't tell where the types come from in C#... but in practice, I don't find that to be a problem. How often are you actually looking at code and can't use Visual Studio?

2) You can use the same convention in .NET too, of course - and I do, although I don't have empty directories going up the chain... so if I'm creating a project with a default namespace of X.Y, then X.Y.Foo would be in Foo.cs, and X.Y.Z.Bar would be in Z\Bar.cs

That's also what Visual Studio will do by default - if you create a subfolder, it will create new classes using a namespace based on the project default and the folder structure.

Of course, you can also declare types in any old file - but mostly people will follow the normal convention of declaring a type with a corresponding filename. Before generics made delegate declarations rarer, I used to have a Delegates.cs file containing all the delegate declarations for a particular namespace (rather than having a bunch of single-declaration files) but these days that's less of an issue.

Jon Skeet
Aren't wildcard imports in Java discouraged from? At least in my own projects, I rarely use them...
Martin S.
@Martin: It depends on the context. If I'm using an IDE for a proper project, I don't use them... if I'm writing throwaway code, they're a simple shortcut. My point is that the language has support for this... likewise you could use aliases for every type used in C#: `using Console=System.Console;` etc. I just wouldn't suggest doing it - because in practice, I haven't found the concerns you've raised to cause practical problems.
Jon Skeet
Yeah, the IDE makes this a non-problem. Sometimes, I just wanted to take a quick look at somebody else's code without importing the whole project/solution in Visual Studio. But I understand that this is a not so common request. Anyway, thanks for your help!
Martin S.
Martin S: Even when you don't use the IDE, it's *usually* fairly easy to find a type - particularly if you know some of the members. For example, search for "msdn httpwebresponse.statuscode" and you'll quickly find the right type, including its namespace. That's if you really *need* to know anyway... which you typically don't when you're just taking a quick look.
Jon Skeet
+2  A: 

1) You're right. There is no "direct" way to know where your class comes from at first glance, but, as you said, you can jump to it in the IDE. But declaring the class this way is just the shortest way to do it. If you wanted, and assuming your Bar class comes from the Foo one, you could declare it

private foo.Bar myBar = new foo.Bar();

This way it would help knowing where your classes come from at first look.

2)When you add a reference to your class, the Add reference windows gives you the informations you are looking for. And if you want to know where they come from after you declared it, there is a window named "Solution Explorer" where you can find these informations, under the "References" tree node. You can set it to be always visible (which it is by default)

nrocha
+1  A: 

For Java and Python this is indeed an issue with conventions - import the class you need, not the entire package using wildcards.

In C# you can't do a using directive for the specific class you want, since it only works for namespaces (as the following error reveals). It would seem that C# remained true to the C++ concept of namespaces, and merged it with the #include directive for one easy way of referencing external classes.

using System.Net.Sockets.Socket; // Gives the following error:

// A using namespace directive can only be applied to namespaces; 
// 'System.Net.Sockets.Socket' is a type not a namespace

And about the double Bar deceleration, it's simple - if the compiler has no way of knowing it will give an error:

using Foo; // Has class Bar {}
using Goo; // Has class Bar {}

Bar b = new Bar(); // Gives the following error:
// 'Bar' is an ambiguous reference between 'Foo.Bar' and 'Goo.Bar'
Eli Iser