Pergunta

Você poderia explicar o que o uso prático é a palavra-chave internal em C #?

Eu sei que a limites modificadoras internal acesso à montagem atual, mas quando e em que circunstâncias devo usá-lo?

Foi útil?

Solução

Classes utilitárias ou auxiliares / métodos que você gostaria de acesso a partir de muitas outras classes dentro do mesmo conjunto, mas que pretende assegurar código em outras montagens não pode acesso.

De MSDN (via archive.org):

Um uso comum de acesso interno está em desenvolvimento baseado em componentes, pois permite que um grupo de componentes para cooperar de forma privada, sem ser exposto ao resto do código do aplicativo. Por exemplo, um quadro para a construção de interfaces gráficas de usuário poderia fornecer classes de controle e de formulário que cooperam usando membros com acesso interno. Uma vez que estes membros são internos, eles não estão expostos ao código que está usando a estrutura.

Você também pode usar o modificador interna, juntamente com a InternalsVisibleTo atributo montagem de nível para criar montagens de "amigo" que são concedidas acesso especial ao alvo montagem classes internas.

Isto pode ser útil para a criação de conjuntos de teste de unidade que são, depois, deixada a chamar os membros internos do conjunto a ser testado. É claro que nenhum outras montagens são concedidos este nível de acesso, então, quando você soltar o seu sistema, o encapsulamento é mantida.

Outras dicas

Se Bob precisa BigImportantClass seguida, Bob precisa obter as pessoas que próprio projeto de A a se inscreverem para garantia de que BigImportantClass será escrito para satisfazer suas necessidades, testados para garantir que ele atenda às suas necessidades, está documentado como satisfazendo as suas necessidades, e que um processo será posto em prática para garantir que ele nunca vai ser alterado, de modo a não satisfazer suas necessidades.

Se uma classe é interna, então ele não tem que passar por esse processo, o que economiza orçamento para o Projeto A de que eles podem gastar em outras coisas.

O ponto de internos que não é que ele torna a vida difícil para Bob. É que ele permite que você controle o que promessas caros Projeto A está fazendo sobre os recursos, tempo de vida, compatibilidade, e assim por diante.

Outra razão para usar interno é se você ofuscar seus binários. O obfuscator sabe que ele é seguro para embaralhar o nome da classe de todas as classes internas, enquanto o nome de classes públicas não podem ser mexidos, porque isso poderia quebrar referências existentes.

Se você estiver escrevendo um DLL que encapsula uma tonelada de funcionalidade complexa em uma API pública simples, em seguida, “interna” é usado em que os alunos que não são para ser exposto ao público.

complexidade Hiding (encapsulamento A.K.A.) é o principal conceito de engenharia de software de qualidade.

A palavra-chave interna é muito utilizada quando você está construindo um wrapper sobre código não-gerenciado.

Quando você tem um C / C ++ biblioteca de base que pretende DllImport você pode importar essas funções como funções estáticas de uma classe, e fazer eles interna, então o usuário só tem acesso ao seu invólucro e não a API original, de modo que não pode mexer com qualquer coisa. As funções sendo estática você pode usar eles em todos os lugares na assembleia, para as múltiplas classes de mensagens publicitárias que você precisa.

Você pode dar uma olhada em Mono.Cairo, é um invólucro em torno da biblioteca cairo que usa essa abordagem.

sendo conduzido por "uso como modificador rigorosas quanto você pode" governar eu uso interno em todos os lugares que eu preciso de acesso, por exemplo, o método de outra classe até que eu explicitamente precisar acessá-lo a partir de outra montagem.

Como a montagem de interface geralmente é mais estreito que a soma de suas classes de interfaces, há muito muitos lugares que eu usá-lo.

Eu acho interna a ser muito usado em demasia. você realmente não deve ser expor certa functionailty apenas para certas classes que você não iria a outros consumidores.

Isso na minha opinião quebra a interface, quebra a abstração. Isso não quer dizer que nunca deve ser usado, mas a melhor solução é refatorar a uma classe diferente ou para ser usado de uma maneira diferente, se possível. No entanto, isso pode não ser sempre possível.

As razões que podem causar problemas é que outro desenvolvedor pode ser cobrado com a construção de uma outra classe no mesmo assembly que o seu é. Tendo internos diminui a clareza da abstração, e pode causar problemas se a ser mal utilizado. Seria o mesmo problema que se tornou público. A outra classe que está sendo construído pelo outro desenvolvedor ainda é um consumidor, assim como qualquer classe externa. Classe abstração e is not encapsulamento apenas para proteção para / de classes externas, mas para qualquer e todas as classes.

Outro problema é que um monte de desenvolvedores irá pensar que pode precisar usá-lo em outras partes da montagem e marcá-lo como interna de qualquer maneira, mesmo que eles não precisam disso na época. Outro desenvolvedor, em seguida, pode pensar que o seu lá para a tomada. Normalmente, você quer marcar como particular até que você tenha uma necessidade definative.

Mas alguns isso pode ser subjetiva, e eu não estou dizendo que nunca deve ser usado. Basta usar quando necessário.

Saw interessante no outro dia, talvez semana, em um blog que eu não me lembro. Basicamente, eu não posso levar o crédito por isso, mas eu pensei que poderia ter alguma aplicação útil.

Say você queria uma classe abstrata para ser visto por uma outra montagem, mas você não quer que alguém seja capaz de herdar a partir dele. Selado não vai funcionar porque é abstrato por um motivo, outras classes em que a montagem herdam a partir dele. Privado não vai funcionar porque você pode querer declarar um em algum lugar da classe pai na outra montagem.

namespace Base.Assembly
{
  public abstract class Parent
  {
    internal abstract void SomeMethod();
  }

  //This works just fine since it's in the same assembly.
  public class ChildWithin : Parent
  {
    internal override void SomeMethod()
    {
    }
  }
}

namespace Another.Assembly
{
  //Kaboom, because you can't override an internal method
  public class ChildOutside : Parent
  {
  }

  public class Test 
  { 

    //Just fine
    private Parent _parent;

    public Test()
    {
      //Still fine
      _parent = new ChildWithin();
    }
  }
}

Como você pode ver, isso efetivamente permite que alguém use a classe Parent sem poder herdar.

Este exemplo contém dois arquivos: Assembly1.cs e Assembly2.cs. O primeiro arquivo contém uma classe base interna, ClasseBase. No segundo arquivo, uma tentativa de ClasseBase instanciar produzirá um erro.

// Assembly1.cs
// compile with: /target:library
internal class BaseClass 
{
   public static int intM = 0;
}

// Assembly1_a.cs
// compile with: /reference:Assembly1.dll
class TestAccess 
{
   static void Main()
   {  
      BaseClass myBase = new BaseClass();   // CS0122
   }
}

Neste exemplo, usar os mesmos arquivos que você usou no exemplo 1, e alterar o nível de acessibilidade de ClasseBase para público . Também alterar o nível de acessibilidade do Intm membro a interno. Neste caso, você pode instanciar a classe, mas você não pode acessar o membro interno.

// Assembly2.cs
// compile with: /target:library
public class BaseClass 
{
   internal static int intM = 0;
}

// Assembly2_a.cs
// compile with: /reference:Assembly1.dll
public class TestAccess 
{
   static void Main() 
   {      
      BaseClass myBase = new BaseClass();   // Ok.
      BaseClass.intM = 444;    // CS0117
   }
}

source : http: //msdn.microsoft.com/en-us/library/7c5ka91b(VS.80).aspx

Um uso muito interessante de interna - com o membro interno do curso que está sendo limitado apenas à montagem na qual é declarada - está ficando funcionalidade "amigo" em algum grau de fora. Um membro do amigo é algo que é visível apenas para certos outros conjuntos fora da assembléia em que o seu declarado. C # não tem suporte embutido para o amigo, no entanto, o CLR faz.

Você pode usar InternalsVisibleToAttribute para declarar um amigo montagem, e todas as referências de dentro do amigo assembleia irá tratar os membros internos do seu declarando montagem como pública no âmbito do amigo montagem. Um problema com isto é que todos os membros internos são visíveis; você não pode escolher.

Um bom uso para InternalsVisibleTo é expor vários membros internos para um teste de unidade eliminando a montagem, assim, as necessidades de complexos arounds reflexão de trabalho para testar os membros. Todos os membros internos sendo visível não é tanto de um problema, no entanto esta abordagem faz muck acima de suas interfaces de classe muito fortemente e pode potencialmente encapsulamento ruína dentro da declarando montagem.

Quando você tem métodos, classes, etc, que precisam ser acessível no âmbito da montagem atual e nunca fora dela.

Por exemplo, uma DAL pode ter um ORM mas os objetos não devem ser expostas à camada de negócios toda a interação deve ser feito através de métodos estáticos e passando nas paramters necessários.

Como regra de polegar, existem dois tipos de membros:

  • superfície pública : visível a partir de um conjunto externo (público, protegido, e interno protegido): chamador não é confiável, então é necessária a validação de parâmetros, documentação do método, etc..
  • superfície privada : não visível a partir de um conjunto externo (aulas particulares e internos, ou internas): chamador é geralmente de confiança, de modo a validação de parâmetros, documentação do método, etc. podem ser omitidos.

A redução de ruído, os tipos menos você expor o mais simples a sua biblioteca é. Adulteração de provas / Segurança é outra (embora reflexão pode ganhar contra ele).

classes internas lhe permitem limitar a API do seu conjunto. Isto tem benefícios, como fazer a sua API simples de entender.

Além disso, se existe um bug no seu conjunto, há menos de uma chance da correção da introdução de uma alteração significativa. Sem classes internas, você teria que assumir que a mudança de membros públicos de qualquer classe seria uma mudança de ruptura. Com classes internas, você pode assumir que modificar seus membros públicos só quebra a API interna do conjunto (e quaisquer assembleias referenciado no atributo InternalsVisibleTo).

Gosto de ter encapsulação ao nível da classe e no nível de montagem. Há alguns que não concordam com isso, mas é bom saber que a funcionalidade está disponível.

Eu tenho um projeto que usa LINQ to SQL para o back-end de dados. Eu tenho dois namespaces principais: Biz e Dados. O modelo de dados LINQ vive em dados e está marcado como "interno"; o namespace Biz tem aulas públicas que envolvem em torno as classes de dados LINQ.

Portanto, há Data.Client e Biz.Client; os últimos expõe todas as propriedades relevantes do objeto de dados, por exemplo:.

private Data.Client _client;
public int Id { get { return _client.Id; } set { _client.Id = value; } }

Os objetos Biz ter um construtor privado (para forçar o uso de métodos de fábrica), e um construtor interno, que se parece com isso:

internal Client(Data.Client client) {
    this._client = client;
}

Isso pode ser usado por qualquer uma das classes de negócios na biblioteca, mas o front-end (UI) não tem como acessar diretamente o modelo de dados, assegurando que a camada de negócios sempre age como intermediário.

Esta é a primeira vez que eu realmente utilizado internal muito, e está provando bastante útil.

Há casos em que faz sentido para fazer membros de classes internal. Um exemplo poderia ser se você quiser controlar como as aulas são instanciado; Vamos dizer que você fornecer algum tipo de fábrica para criar instâncias da classe. Você pode fazer o internal construtor, para que a fábrica (que reside no mesmo conjunto) pode criar instâncias da classe, mas fora do código de que a montagem não pode.

No entanto, eu não posso ver qualquer ponto em fazer classes ou membros internal sem razões específicas, tão pouco como faz sentido fazê-los public, ou private sem razões específicas.

A única coisa que já usou a palavra-chave interno sobre é o código de verificação de licença em meu produto; -)

Um uso da palavra-chave interna é limitar o acesso a implementações concretas por parte do utilizador do seu conjunto.

Se você tem uma fábrica ou algum outro local central para a construção de objetos que o usuário de sua necessidade de montagem apenas lidar com a interface pública ou classe base abstrata.

Além disso, construtores internos permitem controlar onde e quando uma classe de outra forma pública é instanciado.

Como sobre este: normalmente é recomendável que você não exponha um objeto de lista para usuários externos de uma montagem, em vez expor um IEnumerable. Mas é muito mais fácil de usar um objeto de lista dentro do conjunto, porque você começa a sintaxe array, e todos os outros métodos de lista. Então, eu normalmente têm uma propriedade interna expor uma lista para ser usado dentro do conjunto.

Comentários são bem-vindos sobre esta abordagem.

Tenha em mente que qualquer classe definida como public irá aparecer automaticamente no intellisense quando alguém olha para o seu namespace projeto. De uma perspectiva de API, é importante para mostrar apenas os usuários de seu projeto as classes que podem usar. Utilizar a palavra-chave internal para esconder coisas que não deveriam ver.

Se o seu Big_Important_Class para o Projeto A se destina para uso fora seu projeto, então você não deve marcá-lo internal.

No entanto, em muitos projetos, muitas vezes você vai ter aulas que são realmente destinados apenas para uso dentro de um projeto. Por exemplo, você pode ter uma classe que contém os argumentos para uma invocação fio parametrizado. Nestes casos, você deve marcá-los como internal se por nenhuma outra razão do que para proteger-se de uma mudança de API não intencional abaixo da estrada.

A idéia é que quando você está projetando uma biblioteca apenas as classes que são destinados para uso a partir do exterior (por clientes de sua biblioteca) devem ser públicos. Desta forma, você pode se esconder classes que

  1. são susceptíveis de alteração em versões futuras (se fossem pública que você iria quebrar o código do cliente)
  2. são inúteis para o cliente e pode causar confusão
  3. não são seguros (use de modo inadequado pode quebrar sua biblioteca muito mal)

etc.

Se você estiver desenvolvendo inhouse soluções do que usando elementos internos não é tão importante, eu acho, porque geralmente os clientes terão contato constante com você e / ou o acesso ao código. Eles são bastante crítico para desenvolvedores biblioteca embora.

Quando você tem classes ou métodos que não encaixam corretamente no paradigma orientado a objetos, o que fazer coisas perigosas, que precisam ser chamado a partir de outras classes e métodos sob seu controle, e que você não quer deixar qualquer um uso mais.

public class DangerousClass {
    public void SafeMethod() { }
    internal void UpdateGlobalStateInSomeBizarreWay() { }
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top