Почему части пространства имен считаются пространством имен - PullRequest
0 голосов
/ 29 апреля 2020

У меня есть пространство имен, которое выглядит следующим образом:

namespace MyCompany.AspDotNet.Extensions.HttpClient

Затем у меня есть метод, объявленный в этом файле следующим образом:

public static async Task<HttpClient> AddAuthentication(this HttpClient httpClient)

, который выдает ошибку, которая говорит:

HttpClient является пространством имен, но используется как тип
Имя типа ожидается, но пространство имен найдено

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

У меня вопрос, почему он это делает?

Я хочу понять, какое значение. Net получает из-за того, что каждая точка, расположенная на расстоянии части пространства имен, сама по себе считается пространством имен. Можно ли как-то использовать только часть пространства имен?

В качестве дополнительной стороны, есть ли приемлемый обходной путь к этому? Идеи, которые приходят на ум:

  • Подчеркнуть интервал : MyCompany_AspDotNet_Extensions_HttpClient
  • Строчные имена : mycompany.aspdo tnet .extensions .httpclient
  • Полностью ссылаться на все конфликтующие типы : Task<HttpClient> на Task<System.Net.Http.HttpClient>
  • Не использовать никакие типы в именах моего пространства имен : MyCompany.AspDo tNet .Extensions.WebCalls

Я не фанат большинства из них. Но если мне придется выбрать один, я буду go с последним. Но когда я это делаю, я обнаруживаю, что пытаюсь найти другое имя для того, что уже имеет доброе имя.

Ответы [ 3 ]

2 голосов
/ 29 апреля 2020

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

Один из способов исправить это - указать полное имя типа, на которое мы ссылаемся в методе расширения, поскольку одно только имя конфликтует с (более локальным) пространством имен:

namespace MyCompany.Extensions.HttpClient
{
    public static class HttpClientExtensions
    {
        public static async Task<System.Net.Http.HttpClient> AddAuthentication(
            this System.Net.Http.HttpClient httpClient)
        {
            // Extension method implementation here
        }
    }
}

Еще один способ решить эту проблему - поместить оператор using в пространство имен, а не снаружи, поэтому компилятор сначала находит его:

namespace MyCompany.AspDotNet.Extensions.HttpClient
{
    using System.Net.Http;

    public static class HttpClientExtensions
    {
        public static async Task<HttpClient> AddAuthentication(this HttpClient httpClient)
        {
            // Extension method implementation here
        }
    }
}

Но, возможно, лучший способ исправить это, чтобы просто иметь единственное пространство имен для всех методов расширения, а затем создавать классы для каждого типа, например class HttpClientExtensions. Это также устранит конфликт имен и уменьшит общее количество необходимых пространств имен (немного избыточно иметь такое специфическое c имя пространства имен для методов расширения, поскольку в любом случае им необходимо жить в классе).

Например:

namespace MyCompany.ExtensionMethods
{
    public static class HttpClientExtensions
    {
        public static async Task<HttpClient> AddAuthentication(this HttpClient httpClient)
        {
            // Extension method implementation here
        }
    }
}
1 голос
/ 29 апреля 2020

C# компилятор просто работает таким образом. Когда он находит неизвестный идентификатор, он поднимается в область действия и пытается сопоставить его с чем-то. В вашем случае это пространство имен. И поскольку он ожидает тип, он будет жаловаться.

Этого не произойдет, если вы полностью определите тип HttpClient или даже если вы включите директиву using после пространства имен (в этом случае компилятор найдет ваш введите, прежде чем пространство имен станет проблемой).

namespace MyCompany.AspDotNet.Extensions.HttpClient
{
  using System.Net.Http;

  // ...
  public static async Task<HttpClient> AddAuthentication(this HttpClient httpClient)
  // ...
}

Обычно вы не хотите включать имя класса в его пространство имен (хотя, строго говоря, вы на самом деле не делаете это здесь). Вместо этого вы можете попытаться сгруппировать классы по их назначению, технологии или тому подобному. В этом отношении ваш последний пример (MyCompany.AspDotNet.Extensions.WebCalls) лучше других в вашем списке.

Некоторые примеры

MyCompany.AspDotNet.Extensions.Web // every ASP.NET extension (?)
MyCompany.AspDotNet.Extensions.Client // extensions for when we act as a client
MyCompany.AspDotNet.Extensions.Communication // extensions for communicating between client and server
MyCompany.AspDotNet.Extensions.Http // only http communication extensions
MyCompany.AspDotNet.Extensions.Http.Serialization // only for some special serialization over HTTP
MyCompany.AspDotNet.Extensions // or just put everything in one namespace (and group them later, when you realize you can't find anything anymore)
1 голос
/ 29 апреля 2020

Как другие ответы здесь, как исправить это, я устраню вашу путаницу:

namespace MyCompany.AspDotNet.Extensions.HttpClient

У вас нет одного пространства имен с именем MyCompany.AspDotNet.Extensions.HttpClien. У вас есть пространство имен HttpClient, вложенное в пространство имен Extensions, вложенное в пространство имен AspDotNet, вложенное в пространство имен MyCompany. Вот как работает C# (и большинство похожих языков).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...