Respostas:
O maior uso de classes parciais é facilitar a vida dos geradores / designers de código. Classes parciais permitem que o gerador simplesmente emita o código necessário e não precisa lidar com as edições do usuário no arquivo. Da mesma forma, os usuários podem anotar a classe com novos membros, tendo uma segunda classe parcial. Isso fornece uma estrutura muito limpa para a separação de preocupações.
Uma maneira melhor de ver isso é ver como os designers funcionavam antes das classes parciais. O designer do WinForms cuspia todo o código dentro de uma região com comentários fortes sobre não modificar o código. Ele precisava inserir todos os tipos de heurísticas para encontrar o código gerado para processamento posterior. Agora ele pode simplesmente abrir o arquivo designer.cs e ter um alto grau de confiança de que ele contém apenas código relevante para o designer.
Outro uso é dividir a implementação de diferentes interfaces, por exemplo:
partial class MyClass : IF1, IF2, IF3
{
// main implementation of MyClass
}
partial class MyClass
{
// implementation of IF1
}
partial class MyClass
{
// implementation of IF2
}
Implements
palavra-chave para indicar que um método pertence a uma interface)
Além das outras respostas ...
Eu os achei úteis como um trampolim na refatoração de classes divinas. Se uma classe tem várias responsabilidades (especialmente se for um arquivo de código muito grande), acho útil adicionar 1x classe parcial por responsabilidade como primeira passagem para organizar e refatorar o código.
Isso ajuda muito, pois pode ajudar a tornar o código muito mais legível, sem afetar o comportamento de execução. Também pode ajudar a identificar quando uma responsabilidade é fácil de refatorar ou está totalmente confusa com outros aspectos.
No entanto - para ser claro - esse código ainda é ruim, no final do desenvolvimento você ainda deseja uma responsabilidade por classe ( NÃO por classe parcial). É apenas um trampolim :)
Apenas declaração de método parcial Mesmo o código é compilado apenas com declaração de método e, se a implementação do método não estiver presente, o compilador pode remover com segurança esse trecho de código e nenhum erro em tempo de compilação ocorrerá.
Para verificar o ponto 4. Crie um projeto winform e inclua esta linha após o Construtor Form1 e tente compilar o código
partial void Ontest(string s);
Aqui estão alguns pontos a serem considerados ao implementar classes parciais: -
Um ótimo uso é separar o código gerado do código escrito à mão que pertence à mesma classe.
Por exemplo, como o LINQ to SQL usa classes parciais, você pode escrever sua própria implementação de certas partes da funcionalidade (como relacionamentos Muitos-para-Muitos) e essas partes do código personalizado não serão substituídas quando você gerar novamente o código.
O mesmo vale para o código WinForms. Todo o código gerado pelo Designer entra em um arquivo no qual você geralmente não toca. Seu código escrito à mão entra em outro arquivo. Dessa forma, quando você altera algo no Designer, suas alterações não são exageradas.
É verdade que a classe parcial é usada na geração automática de código; um uso pode ser manter um arquivo de classe grande que pode ter milhares de linhas de código. Você nunca sabe que sua turma pode terminar com 10 mil linhas e não deseja criar uma nova turma com nome diferente.
public partial class Product
{
// 50 business logic embedded in methods and properties..
}
public partial class Product
{
// another 50 business logic embedded in methods and properties..
}
//finally compile with product.class file.
Outro uso possível pode ser que mais de um desenvolvedor possa trabalhar na mesma classe em que são armazenados em locais diferentes. As pessoas podem rir, mas você nunca sabe que às vezes pode ser um punhado.
public partial class Product
{
//you are writing the business logic for fast moving product
}
public partial class Product
{
// Another developer writing some business logic...
}
Espero que faça sentido!
Classes parciais abrangem vários arquivos.
Como você pode usar o modificador parcial em uma declaração de classe C #?
Com classes parciais, você pode separar fisicamente uma classe em vários arquivos. Isso geralmente é feito por geradores de código.
Exemplo
Com classes C # normais, você não pode declarar uma classe em dois arquivos separados no mesmo projeto. Mas com o partial
modificador, você pode.
Isso é útil se um arquivo é normalmente editado e o outro é gerado por máquina ou raramente editado.
Aqui está um exemplo para esclarecer:
class Program
{
static void Main()
{
A.A1();
A.A2();
}
}
Conteúdo do arquivo A1.cs: C #
using System;
partial class A
{
public static void A1()
{
Console.WriteLine("A1");
}
}
Conteúdo do arquivo A2.cs: C #
using System;
partial class A
{
public static void A2()
{
Console.WriteLine("A2");
}
}
Resultado:
A1
A2
Parcial é necessário aqui.
Se você remover o partial
modificador, você receberá um erro contendo este texto:
[O espaço para nome '
<global namespace>
' já contém uma definição para 'A
'].
Gorjeta:
Para corrigir isso, você pode usar o partial
palavra chave ou alterar um dos nomes de classe.
Como o compilador C # lida com classes parciais?
Se você desmontar o programa acima (usando o IL Disassembler), verá que os arquivos A1.cs e A2.cs são eliminados. Você verá que a classe A está presente.
A classe A conterá os métodos A1 e A2 no mesmo bloco de código. As duas classes foram mescladas em uma.
Resultado compilado de A1.cs e A2.cs: C #
internal class A
{
// Methods
public static void A1()
{
Console.WriteLine("A1");
}
public static void A2()
{
Console.WriteLine("A2");
}
}
Sumário
mantenha tudo o mais limpo possível ao trabalhar com grandes classes ou ao trabalhar em equipe, você pode editar sem substituir (ou sempre confirmar alterações)
Se você tem uma classe suficientemente grande que não se presta a uma refatoração eficaz, separá-la em vários arquivos ajuda a manter as coisas organizadas.
Por exemplo, se você possui um banco de dados para um site que contém um fórum de discussão e um sistema de produtos e não deseja criar duas classes de provedores diferentes (NÃO a mesma coisa que uma classe de proxy, só para esclarecer), você pode crie uma única classe parcial em arquivos diferentes, como
MyProvider.cs - lógica central
MyProvider.Forum.cs - métodos pertencentes especificamente ao fórum
MyProvider.Product.cs - métodos para produtos
É apenas outra maneira de manter as coisas organizadas.
Além disso, como outros já disseram, é a única maneira de adicionar métodos a uma classe gerada sem correr o risco de destruir suas adições na próxima vez que a classe for regenerada. Isso é útil com código gerado por modelo (T4), ORMs etc.
Como uma alternativa às diretivas pré-compilador.
Se você usar as diretivas de pré-compilador (ou seja #IF DEBUG
), você acaba com algum código de aparência gnarly misturado com o código de versão atual.
Você pode criar uma classe parcial separada para conter esse código e agrupar toda a classe parcial em uma diretiva ou omitir que esse arquivo de código seja enviado ao compilador (efetivamente fazendo o mesmo).
As referências de serviço são outro exemplo em que classes parciais são úteis para separar o código gerado do código criado pelo usuário.
Você pode "estender" as classes de serviço sem substituí-las quando atualizar a referência de serviço.
Outro uso que vi é,
Estendendo uma grande classe abstrata sobre lógica de acesso a dados,
Eu tenho vários arquivos com nomes Post.cs, Comment.cs, Pages.cs ...
in Post.cs
public partial class XMLDAO :BigAbstractClass
{
// CRUD methods of post..
}
in Comment.cs
public partial class XMLDAO :BigAbstractClass
{
// CRUD methods of comment..
}
in Pages.cs
public partial class XMLDAO :BigAbstractClass
{
// CRUD methods of Pages..
}
A maioria das pessoas observa que partial
só deve ser usado para uma classe que tenha um arquivo de código gerado ou para interfaces. Eu discordo, e aqui está o porquê.
Por um exemplo, vejamos a classe C # System.Math ... essa é a classe . Eu não tentaria inserir mais de 70 métodos no mesmo arquivo de código único. Seria um pesadelo para manter.
A colocação de cada método matemático em arquivos de classes parciais individuais e todos os arquivos de código em uma pasta Math no projeto seria uma organização significativamente mais limpa.
O mesmo poderia / seria válido para muitas outras classes que possuem uma grande quantidade de funcionalidades diversas. Por exemplo, uma classe para gerenciar a API PrivateProfile pode se beneficiar ao ser dividida em um conjunto limpo de arquivos de classe parciais em uma única pasta do projeto.
Pessoalmente, também divido o que a maioria das pessoas chama de classes "auxiliar" ou "utilitário" em arquivos parciais individuais para cada método ou grupo funcional do método. Por exemplo, em um projeto, a classe helper de strings possui quase 50 métodos. Isso seria um arquivo de código longo e pesado, mesmo usando regiões. É significativamente mais fácil manter o uso de arquivos de classes parciais individuais para cada método.
Eu seria cuidadoso ao usar classes parciais e manteria todo o layout do arquivo de código consistente durante todo o projeto ao fazer isso. Como colocar qualquer enumeração pública de classe e membros privados de classe em um arquivo Common.cs ou com nome semelhante na pasta, em vez de espalhá-los pelos arquivos, a menos que sejam específicos apenas ao arquivo parcial em que estão contidos.
Lembre-se de que, ao dividir uma classe em arquivos separados, você também perde a capacidade de usar a barra divisória do editor de texto que permite exibir duas seções diferentes de um arquivo atual simultaneamente.
Classes parciais tornam possível adicionar funcionalidade a um programa adequadamente projetado apenas adicionando arquivos de origem. Por exemplo, um programa de importação de arquivos pode ser projetado para adicionar diferentes tipos de arquivos conhecidos, adicionando módulos que os tratam. Por exemplo, o principal conversor de tipo de arquivo pode incluir uma classe pequena:
Classe pública parcial zzFileConverterRegistrar Registro de Eventos (ByVal mainConverter como zzFileConverter) Sub registerAll (ByVal mainConverter como zzFileConverter) Registro RaiseEvent (mainConverter) End Sub Classe final
Cada módulo que deseja registrar um ou mais tipos de conversor de arquivos pode incluir algo como:
Classe pública parcial zzFileConverterRegistrar Private Sub RegisterGif (ByVal mainConverter como zzFileConverter) manipula Me.Register mainConverter.RegisterConverter ("GIF", GifConverter.NewFactory)) End Sub Classe final
Observe que a classe principal do conversor de arquivos não está "exposta" - apenas expõe uma pequena classe de stub à qual os módulos complementares podem ser conectados. Há um pequeno risco de conflitos de nomeação, mas se a rotina de "registro" de cada módulo de suplemento for nomeada de acordo com o tipo de arquivo com o qual lida, eles provavelmente não deverão representar um problema. Alguém poderia colocar um GUID no nome da sub-rotina de registro se estivesse preocupado com essas coisas.
Editar / Adendo Para ser claro, o objetivo disso é fornecer um meio pelo qual uma variedade de classes separadas possa informar um programa ou classe principal sobre elas. A única coisa que o conversor de arquivo principal fará com zzFileConverterRegistrar é criar uma instância e chamar o método registerAll, que acionará o evento Register. Qualquer módulo que queira ligar esse evento pode executar código arbitrário em resposta a ele (essa é a idéia toda), mas não há nada que um módulo possa fazer estendendo indevidamente a classe zzFileConverterRegistrar além de definir um método cujo nome corresponda ao de outra coisa . Certamente seria possível que uma extensão gravada incorretamente quebrasse outra extensão gravada incorretamente, mas a solução para isso é para quem não quer que sua extensão seja quebrada, simplesmente a escreva corretamente.
Alguém poderia, sem usar classes parciais, ter um pouco de código em algum lugar da classe principal do conversor de arquivos, que se parecia com:
RegisterConverter ("GIF", GifConvertor.NewFactory) RegisterConverter ("BMP", BmpConvertor.NewFactory) RegisterConverter ("JPEG", JpegConvertor.NewFactory)
mas adicionar outro módulo do conversor exigiria entrar nessa parte do código do conversor e adicionar o novo conversor à lista. Usando métodos parciais, isso não é mais necessário - todos os conversores serão incluídos automaticamente.
IModule
interface?
IModule
, você pode usar uma estrutura de plug-ins como o MEF (apenas um de muitos), etc. etc.
Classes parciais recentemente ajudaram no controle de origem, onde vários desenvolvedores foram adicionando a um arquivo em que novos métodos foram adicionados à mesma parte do arquivo (automatizado pelo Resharper).
Esses impulsos para o git causaram conflitos de mesclagem. Não encontrei nenhuma maneira de dizer à ferramenta de mesclagem para usar os novos métodos como um bloco de código completo.
As classes parciais a esse respeito permitem que os desenvolvedores se apegem a uma versão de seu arquivo, e podemos mesclá-las mais tarde manualmente.
exemplo -
Do MSDN :
1.No momento da compilação, os atributos das definições de tipo parcial são mesclados. Por exemplo, considere as seguintes declarações:
[SerializableAttribute]
partial class Moon { }
[ObsoleteAttribute]
partial class Moon { }
Eles são equivalentes às seguintes declarações:
[SerializableAttribute]
[ObsoleteAttribute]
class Moon { }
A seguir, são mescladas de todas as definições de tipo parcial:
Comentários XML
interfaces
atributos de parâmetro do tipo genérico
atributos de classe
membros
2. Outra coisa, as classes parciais aninhadas também podem ser parciais:
partial class ClassWithNestedClass
{
partial class NestedClass { }
}
partial class ClassWithNestedClass
{
partial class NestedClass { }
}
Aqui está uma lista de algumas das vantagens das classes parciais.
É possível separar o código de design da interface do usuário e o código da lógica de negócios para facilitar a leitura e compreensão. Por exemplo, você está desenvolvendo um aplicativo Web usando o Visual Studio e adiciona um novo formulário da Web. Existem dois arquivos de origem, "aspx.cs" e "aspx.designer.cs". Esses dois arquivos têm a mesma classe com a palavra-chave parcial. A classe ".aspx.cs" possui o código de lógica de negócios, enquanto "aspx.designer.cs" possui a definição de controle da interface do usuário.
Ao trabalhar com a fonte gerada automaticamente, o código pode ser adicionado à classe sem a necessidade de recriar o arquivo de origem. Por exemplo, você está trabalhando com LINQ to SQL e cria um arquivo DBML. Agora, quando você arrasta e solta uma tabela, ela cria uma classe parcial no designer.cs e todas as colunas da tabela têm propriedades na classe. Você precisa de mais colunas nesta tabela para vincular à grade da interface do usuário, mas não deseja adicionar uma nova coluna à tabela do banco de dados para poder criar um arquivo de origem separado para esta classe que tenha uma nova propriedade para essa coluna e ser uma classe parcial. Isso afeta o mapeamento entre a tabela do banco de dados e a entidade DBML, mas é possível obter facilmente um campo extra. Isso significa que você pode escrever o código sozinho, sem mexer no código gerado pelo sistema.
Mais de um desenvolvedor pode escrever simultaneamente o código da classe.
Você pode manter sua aplicação melhor compactando classes grandes. Suponha que você tenha uma classe que tenha várias interfaces para poder criar vários arquivos de origem, dependendo dos implementos da interface. É fácil entender e manter uma interface implementada na qual o arquivo de origem possui uma classe parcial.
Sempre que tenho uma classe que contém uma classe aninhada de qualquer tamanho / complexidade significativa, eu marquei a classe como partial
e coloco a classe aninhada em um arquivo separado. Eu nomeio o arquivo que contém a classe aninhada usando a regra: [nome da classe]. [Nome da classe aninhada] .cs.
O blog do MSDN a seguir explica como usar classes parciais com classes aninhadas para manutenção: http://blogs.msdn.com/b/marcelolr/archive/2009/04/13/using-partial-classes-with-nested-classes-for- manutenibilidade.aspx
Eu sei que essa pergunta é muito antiga, mas eu gostaria de adicionar minha opinião sobre as aulas parciais.
Uma razão pela qual eu pessoalmente uso classes parciais é quando estou criando ligações para um programa, especialmente máquinas de estado.
Por exemplo, OpenGL é uma máquina de estado, existem montes de métodos que podem ser alteradas globalmente, no entanto, na minha experiência algo semelhante ao OpenGL onde existem tantos métodos de ligação, a classe pode facilmente exceder 10k LOC.
Classes parciais dividirão isso para mim e me ajudarão a encontrar métodos rapidamente.
As classes parciais são introduzidas principalmente para ajudar os geradores de código, para que nós (usuários) não acabemos perdendo todo o nosso trabalho / alterações nas classes geradas, como a classe .designer.cs do ASP.NET cada vez que regeneramos, quase todas as novas ferramentas que geram O código LINQ, EntityFrameworks, ASP.NET usa classes parciais para o código gerado, para que possamos adicionar ou alterar com segurança a lógica desses códigos gerados, aproveitando as classes e métodos Parciais, mas tenha muito cuidado antes de adicionar itens ao código gerado usando classes Parciais é mais fácil se quebrarmos a compilação, mas pior se introduzirmos erros de tempo de execução. Para obter mais detalhes, consulte este site http://www.4guysfromrolla.com/articles/071509-1.aspx
Observo dois usos que não consegui encontrar explicitamente nas respostas.
Alguns desenvolvedores usam comentários para separar "partes" diferentes de sua classe. Por exemplo, uma equipe pode usar a seguinte convenção:
public class MyClass{
//Member variables
//Constructors
//Properties
//Methods
}
Com classes parciais, podemos dar um passo adiante e dividir as seções em arquivos separados. Como convenção, uma equipe pode sufocar cada arquivo com a seção correspondente a ele. Portanto, acima, teríamos algo como: MyClassMembers.cs, MyClassConstructors.cs, MyClassProperties.cs, MyClassMethods.cs.
Como outras respostas mencionadas, se vale ou não a pena dividir a classe provavelmente depende de quão grande é a classe nesse caso. Se for pequeno, provavelmente é mais fácil ter tudo em uma aula de mestre. Mas se qualquer uma dessas seções ficar muito grande, seu conteúdo poderá ser movido para uma classe parcial separada, a fim de manter a classe principal limpa. Uma convenção nesse caso pode ser deixar um comentário dizendo algo como "Ver classe parcial" após o cabeçalho da seção, por exemplo:
//Methods - See partial class
Provavelmente é uma ocorrência rara, mas pode haver uma colisão de namespace entre duas funções das bibliotecas que você deseja usar. Em uma única classe, você pode usar no máximo uma cláusula using para um deles. Para o outro, você precisará de um nome completo ou um alias. Com classes parciais, uma vez que cada namespace e lista de instruções de uso são diferentes, é possível separar os dois conjuntos de funções em dois arquivos separados.
using Library1 = The.Namespace.You.Need
ouglobal::Root.Of.Namespace