Por que usar classes parciais?

72

No meu entendimento, a palavra-chave partial não faz nada além de permitir que uma classe seja dividida entre vários arquivos de origem. Existe alguma razão para fazer isso além da organização do código? Eu vi isso usado para isso em classes de interface do usuário geradas.

Parece um motivo ruim para criar uma palavra-chave inteira. Se uma classe é grande o suficiente para exigir vários arquivos, provavelmente está fazendo muito. Eu pensei que talvez você pudesse usá-lo para definir parcialmente uma classe para outro programador em algum lugar para completar, mas seria melhor fazer uma classe abstrata.

    
por Michael K 26.04.2011 / 21:42
fonte

9 respostas

110

É muito útil em todos os cenários em que uma parte da classe é gerada por alguma ferramenta personalizada, pois permite adicionar lógica personalizada ao código gerado sem herdar a classe gerada. Btw. existem também métodos parciais pela mesma razão.

Não é apenas sobre a interface do usuário, mas também outras tecnologias, como o Linq-To-Sql ou o Entity Framework, usam bastante isso.

    
por 26.04.2011 / 21:44
fonte
25

Como você diz, muitas vezes é usado para separar o código gerado. Geralmente não tem nada a ver com o tamanho das classes / arquivos.

O benefício de separar o código gerado é de estilo. O código gerado pode ser bem feio e ilegível e pode falhar em muitos padrões de codificação (e verificações de StyleCop), mas tudo bem, ninguém precisa lê-lo ou mantê-lo diretamente. Então, se você "esconder" em outro arquivo, você pode se concentrar em certificar-se de que o resto da classe esteja de acordo com o padrão, passa no StyleCop e assim por diante.

Outra área em que usei é onde uma classe implementa várias interfaces, pode ser muito bom separar a implementação em arquivos separados, embora isso seja mais uma questão de preferência pessoal, nunca vi nenhuma codificação padrões exigem (ou impedem) isso.

    
por 26.04.2011 / 21:51
fonte
18

Um dos desenvolvedores onde eu trabalho surgiu para um bom uso para eles há algumas semanas na refatoração de grandes classes de Deus que saíram do controle e têm muitos métodos públicos: separando as funções lógicas de Cada bit da classe em classes parciais separadas você pode fisicamente separar a classe em unidades mais atômicas que devem ser as classes sem quebrar qualquer funcionalidade existente, permitindo que você veja o que é comum e o que não é. Com isso como um primeiro estágio, é mais fácil dividir as parciais em suas próprias classes independentes e implementá-las em toda a base de código. Eu pensei que isso era uma boa ideia.

No entanto, em geral, acho que eles só devem ser usados para aumentar as classes geradas por máquina ao escrever um novo código.

    
por 26.04.2011 / 21:54
fonte
17

Posso pensar em alguns cenários úteis em que parciais fazem sentido, a maioria deles estou usando em meus projetos:

  • Para separar o código gerado Ferramenta / IDE / Designer do código que você está mantendo. Um bom exemplo é o arquivo Form.Designer.cs que contém o código gerado pelo designer para aplicativos de formulários do Windows. Muitos outros formatos .NET também possuem algum código gerado por ferramenta, que pode ser potencialmente regenerado quando você cria seu projeto e, portanto, todas as suas alterações personalizadas serão eliminadas. A separação ajudará você a manter seu código e alterações a salvo de tais modificações automatizadas.

  • Quando você está implementando várias interfaces com muito código na implementação. Eu costumo usar um arquivo parcial separado para cada interface, nomeando-o assim: {Class}.{Interface}.cs . É fácil para mim ver no IDE quais interfaces o {Class} está implementando e como.

  • Quando a classe deve conter uma ou mais classes aninhadas , especialmente com código suficiente para ser colocado em um arquivo separado. Eu manteria o padrão acima e usaria a convenção de nomenclatura {Class}.{NestedClass}.cs para cada classe aninhada. Prática semelhante já é mencionada pela resposta da Virtlink .

  • Quando escrevo static classes que contêm métodos de extensão . Muitas vezes, será o caso de fornecer a mesma lógica de método de extensão a classes ou interfaces semelhantes - como por exemplo Reverse em coleções genéricas e não genéricas. Eu colocaria todos os métodos de extensão para uma única classe ou interface em uma parte separada da classe estática. Por exemplo, eu teria todos os métodos de extensão para a interface IList em um local e os mesmos métodos que são para IList<T> em outro arquivo. Outra abordagem seria colocar o mesmo método (todas as suas sobrecargas) na mesma parcial, com todas as classes possíveis para o parâmetro this - como ter todas as implementações Reverse em um arquivo. Depende de qual deles justificaria melhor a separação em termos de volume de código ou algumas convenções internas que você ou sua organização possam estar adotando.

  • Eu não uso isso, mas eu vi algumas pessoas de C / C ++ gostarem da abordagem que descreverei aqui: crie uma parcial para a classe com métodos parciais apenas. Isso se assemelha a maneira C / C ++ para definir interfaces e separar a declaração de método da implementação.

  • Separação por questões puramente lógicas . Se acontecer de você trabalhar com uma classe grande que combina mais de um conjunto de operações lógicas, você pode separar cada código relacionado logicamente em uma parcial separada. Normalmente a existência de tais classes é contra o princípio separação de interesses , mas é frequentemente observado caso da vida real, especialmente para bases de código mais antigas. Seu colega Steve Evers os mencionou em sua resposta a essa pergunta , referindo-se a eles pelo nome god objects . Eu pessoalmente usaria a abordagem de classes parciais para dividir o código antes que qualquer refatoração desses arquivos realmente grandes ocorresse, a fim de facilitar o meu trabalho e tornar a refatoração mais transparente. Isso também reduzirá os conflitos que possivelmente causarei quando sistemas de versão como o SVN estiverem envolvidos.

por 01.04.2014 / 13:28
fonte
14

Eu não vi isso mencionado por ninguém: eu uso partial para colocar classes aninhadas em seus próprios arquivos.

Todos os meus arquivos de código contêm apenas uma classe, struct, interface ou enum. Isso torna muito mais fácil encontrar a definição para um objeto quando os nomes dos arquivos mostram o nome da coisa que você está procurando. E como o Visual Studio tenta corresponder as pastas do projeto aos namespaces, os nomes dos arquivos devem corresponder às classes.

Isso também significa que uma classe NestedClass aninhada dentro de MyClass terá seu próprio arquivo em meus projetos: MyClass.NestedClass.cs .

partial class MyClass
{
    private class NestedClass
    {
        // ...
    }
}
    
por 06.02.2013 / 21:07
fonte
10

Com exceção do uso de código gerado, eu tenho somente visto usá-los em um esforço para encobrir objetos de deus . Tentar entender uma nova base de código ou navegar por vários arquivos de origem, que são o mesmo objeto, é muito chato.

Então, quando você pergunta Why use partial classes? , eu respondo: a menos que você esteja usando código gerado, não.

    
por 26.04.2011 / 22:42
fonte
6

A organização do código é a única razão, mas é mais profunda do que parece à primeira vista. Se você tem aulas parciais onde as peças são geradas, você pode facilmente:

  • Gere novamente o código sem precisar detectar alterações manuais nas classes para as quais você escreve (para não sobrescrever essas partes).
  • Exclua as classes parciais geradas da cobertura de teste, controle de origem, métricas, etc.
  • Use código gerado sem forçar você a basear sua estratégia de herança em torno dele (você ainda pode herdar de outras classes).
por 26.04.2011 / 21:58
fonte
1

Existem também alguns locais onde as classes geradas / implícitas são declaradas parciais, de modo que, se o desenvolvedor precisar estendê-las, elas terão acesso total, sem ter que se preocupar em herdar e substituir por todo o lugar. Observe as classes geradas na área temporária do asp.net depois de executar um site de webforms pela primeira vez no IIS, se quiser tentar obter alguns exemplos.

    
por 26.04.2011 / 22:43
fonte
1

Eu posso pensar em um uso sujo para eles.

Suponha que você tenha algumas classes que precisam de funcionalidade comum, mas você não deseja injetar essa funcionalidade na cadeia de herança acima delas. Ou você tem um conjunto de classes que usam uma classe auxiliar comum.

Basicamente você quer fazer herança múltipla, mas C # não gosta. Então, o que você faz é usar parcial para criar o que é essencialmente um #include em C / C ++;

Coloque toda a funcionalidade em uma classe ou use a classe auxiliar. Em seguida, copie o auxiliar X vezes e renomeie-o como classe parcial A, B, C. e coloque parcial nas suas classes A, B, C.

Disclaimer: Sim, isso é mal. Nunca faça isso - especialmente se isso deixar outras pessoas com raiva de você.

    
por 13.07.2011 / 09:37
fonte