Подтвердить что ты не робот

Пространства имен в С# vs import в Java и Python

В мире Java и Python вы смотрите на исходный файл и знаете, откуда взялись все импорты (т.е. вы знаете, в каком файле определены импортированные классы). Например:

В Java:

import javafoo.Bar;

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

Вы сразу увидите, что класс bar импортируется из javafoo. Итак, Bar объявлен в /javafoo/Bar.java

В Python

import pythonbaz
from pythonfoo import Bar

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

Здесь ясно, что Bar происходит из пакета pythonfoo, а Other - явно из pythonbaz.

В С# (исправьте меня, если я ошибаюсь):

using foo
using baz
using anothernamespace
...

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

Два вопроса:
1) Как узнать, где объявлен класс Bar? Оно исходит из пространства имен foo или bar или anothernamespace? (изменить: без с помощью Visual Studio)

2) В Java имена пакетов соответствуют именам каталогов (или это очень сильное соглашение). Таким образом, когда вы видите, из какого пакета приходит класс, вы знаете его каталог в файловой системе.

В С#, похоже, не существует такого соглашения для пространств имен, или я чего-то не хватает? Итак, как узнать, какой каталог и файл искать (без Visual Studio)? (после выяснения, из какого пространства имен пришел класс).

Изменить пояснения. Я знаю, что Python и/или Java допускают импорт подстановочных знаков, но "культура" на этих языках хмурится ими (по крайней мере, на Python, на Java я не уверен). Кроме того, в Java IDE обычно помогают создавать минимальный импорт (как указано в Mchl ниже)

4b9b3361

Ответ 1

1) Ну, вы тоже можете сделать то же самое на Java:

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

...

InputStream x = ...;

Есть ли InputStream от java.util или java.io? Конечно, вы можете не использовать эту функцию.

Теперь, в теории, я понимаю это, когда вы смотрите текстовым редактором, вы не можете определить, откуда берутся типы из С#... но на практике я не считаю, что это проблема, Как часто вы просматриваете код и не можете использовать Visual Studio?

2) Конечно, вы можете использовать одно и то же соглашение в .NET - и я это делаю, хотя у меня нет пустых каталогов, идущих вверх по цепочке... так что если я создаю проект с пространством имен по умолчанию XY, тогда X.Y.Foo будет в Foo.cs, а XYZBar будет находиться в Z\Bar.cs

То, что Visual Studio будет делать по умолчанию - если вы создадите подпапку, она создаст новые классы, используя пространство имен на основе стандартного проекта и структуры папок.

Конечно, вы также можете объявлять типы в любом старом файле - но в основном люди будут следовать нормальному соглашению об объявлении типа с соответствующим именем файла. До того, как дженерики сделали объявления делегатов более редкими, у меня был файл Delegates.cs, содержащий все объявления делегатов для определенного пространства имен (вместо того, чтобы иметь кучу файлов с одной декларацией), но в эти дни это меньше проблемы.

Ответ 2

1) Ты прав. Не существует "прямого" способа узнать, откуда появился ваш класс с первого взгляда, но, как вы сказали, вы можете перейти к нему в среде IDE. Но объявление класса таким образом - это всего лишь кратчайший способ сделать это. Если бы вы захотели, и если ваш класс Bar появился из Foo, вы можете объявить его

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

Таким образом, это поможет узнать, откуда начинаются ваши классы.

2) Когда вы добавляете ссылку на свой класс, окна добавления ссылок дают вам информацию, которую вы ищете. И если вы хотите знать, откуда они пришли после того, как вы его объявили, есть окно с названием "Solution Explorer", где вы можете найти эту информацию в дереве "Ссылки" node. Вы можете установить его всегда видимым (по умолчанию он)

Ответ 3

Как узнать, где находится класс Bar? объявили? Это происходит из namespace foo или bar, или anothernamespace? Visual Studio позволяет я, конечно, прыгаю туда, но что если я просто быстро посмотрю на исходный файл в моем редакторе?

По существу, вы этого не делаете, но IntelliSense помогает. На самом деле вы не можете быть уверены, просто взглянув на код, но наведите курсор мыши на символ с помощью курсора. Но это также возможно в Python:

from foobar import *
from bazbaz import *

a_bar = Bar()

Откуда появился Bar?

В С#, похоже, нет таких соглашение для пространств имен, или я что-то не хватает? Итак, как я знаю в какой каталог и файл искать? (после определения того, какое пространство имен класс пришел).

Нет, сборки не соответствуют структурам каталогов, что, ИМХО, является хорошей вещью. Исследователь решений предлагает обзор всех ссылок, добавленных в ваш проект. Эти ссылки являются сборками, имеют конкретное представление как PE файл где-то на вашем компьютере. Вы можете легко просмотреть свойства ссылки, чтобы увидеть, где находится физический файл.

Изменить: Чтобы не противоречить другим ответам в этом потоке и создавать путаницу: я имею в виду, говоря, что имена сборок не соответствуют именам каталогов, это то, что они фактически не выполняются.

Ответ 4

В С#, похоже, не существует такого соглашения для пространств имен, или я что-то не хватает?

Я не знаю о других проектах, но я уверен, что в каждом .NET-проекте, над которым я работал, мы использовали это соглашение, т.е. пространства имен всегда соответствовали именам папок (за исключением самых внешних пространств имен, которые соответствуют сборке из которого происходит пространство имен).

Ответ 5

Для Java и Python это действительно проблема с соглашениями - импортируйте требуемый класс, а не весь пакет с помощью подстановочных знаков.

В С# вы не можете сделать директиву using для определенного класса, который вы хотите, поскольку он работает только для пространств имен (как показывает следующая ошибка). Казалось бы, С# остался верен концепции пространств имен С++ и объединил ее с директивой #include для одного простого способа ссылки на внешние классы.

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

И о двойном замедлении Bar, это просто - если компилятор не знает, что он даст ошибку:

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'

Ответ 6

Обычно всплывающая подсказка, когда вы наводите указатель мыши на имя типа, показывает дополнительную информацию. Кроме того, вы всегда можете щелкнуть правой кнопкой мыши имя типа и "Перейти к определению".