Visibilidade de classe apenas de namespace em C # /. NET?


87

Em C #, você pode tornar uma classe visível apenas dentro de seu próprio namespace sem viver em um assembly diferente? Isso parece útil para classes auxiliares típicas que não devem ser usadas em outro lugar. (ou seja, o que Java chama de classes privadas de pacote)


Eu não entendo sua pergunta. Removi minhas respostas porque você não quis dizer "interno"?
Zyphrax

3
@nos: você está procurando o equivalente à visibilidade em nível de pacote do java?
John Saunders

Respostas:



80

Você pode fazer as classes, internalmas isso apenas impede que qualquer pessoa fora da montagem use a classe. Mas você ainda precisa fazer um assembly separado para cada namespace com o qual deseja fazer isso. Presumo que seja por isso que você não gostaria de fazer isso.

Fazendo com que o compilador C # reforce a visibilidade do namespace

Há um artigo aqui ( Visibilidade do namespace em C # ) que mostra um método de uso de classes parciais como uma forma de "namespace falso" que pode ser útil.

O autor aponta que isso não funciona perfeitamente e ele discute as deficiências. O principal problema é que os designers do C # projetaram o C # para não funcionar dessa maneira. Isso se desvia muito das práticas de codificação esperadas em C # /. NET, que é uma das maiores vantagens do .NET Framework.

É um truque bacana ... agora não faça isso.


1
Acabei de encontrar um exemplo:System.Net.Mime.MediaTypeNames.Application
Bitterblue

O artigo diz que você deve prefixar cada chamada com o nome do seu "namespace", mas não precisa disso com C # 6 "usando estático". Você pode tornar o "namespace" uma classe parcial estática e, em seguida, no código do cliente, escrever "usando estática"
Pumkko

@Pumkko A classe não precisa ser estática para poder usar a instrução 'using static', embora se você a estiver usando como um namespace, deveria ser assim mesmo.
Fuzzy Logic de

21

interno é a privacidade de montagem (módulo estritamente falando). Não tem efeito na visibilidade do namespace.

A única maneira de obter privacidade de uma classe de outras classes dentro do mesmo assembly é que uma classe seja uma classe interna.

Nesse ponto, se a classe for privada, ela será invisível para qualquer coisa que não esteja nessa classe ou para a própria classe externa.

Se protegido, é visível para todos que poderiam vê-lo quando privado, mas também é visível para subclasses da classe externa.

public class Outer
{
    private class Hidden     { public Hidden() {} }
    protected class Shady    { public Shady() {} }
    public class Promiscuous { public Promiscuous() {} }
}

public class Sub : Outer
{
    public Sub():base() 
    {
        var h = new Hidden();      // illegal, will not compile
        var s = new Shady();       // legal
        var p = new Promiscuous(); // legal
    }
}

public class Outsider 
{
    public Outsider() 
    {
        var h = new Outer.Hidden();      // illegal, will not compile
        var s = new Outer.Shady()        // illegal, will not compile
        var p = new Outer.Promiscuous(); // legal
    }
}

Em essência, a única maneira de alcançar o que você deseja é usar a classe externa como uma forma de namespace e restringir dentro dessa classe.


@ShuggyCoUK: public class Sub: Externo deve ser selado public class Sub: Externo ??? 1 embora ... funciona para mim
IAbstract

0

Se você tiver uma única montagem, poderá definir quantos namespaces desejar nessa montagem, mas independentemente do modificador que aplicar no IDE, você sempre poderá ver as classes em outros namespaces.


0

Não tenho certeza se isso é diretamente possível, mas algumas boas maneiras de fingir seriam:

1) Faça com que as classes que precisam desse tipo de coisa sejam herdadas de uma única classe que tem a classe auxiliar como uma classe interna.

2) Use métodos de extensão e, em seguida, faça referência apenas aos métodos de extensão dentro do namespace.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.