Réponses:
La plus grande utilisation des classes partielles est de faciliter la vie des générateurs / concepteurs de code. Les classes partielles permettent au générateur d'émettre simplement le code dont il a besoin pour émettre et elles n'ont pas à gérer les modifications utilisateur du fichier. Les utilisateurs sont également libres d'annoter la classe avec de nouveaux membres en ayant une deuxième classe partielle. Cela fournit un cadre très propre pour la séparation des préoccupations.
Une meilleure façon de voir les choses est de voir comment les concepteurs fonctionnaient avant les classes partielles. Le concepteur WinForms cracherait tout le code à l'intérieur d'une région avec des commentaires formulés sur la non-modification du code. Il a dû insérer toutes sortes d'heuristiques pour trouver le code généré pour un traitement ultérieur. Maintenant, il peut simplement ouvrir le fichier designer.cs et avoir un haut degré de confiance qu'il ne contient que du code pertinent pour le concepteur.
Une autre utilisation consiste à diviser la mise en œuvre de différentes interfaces, par exemple:
partial class MyClass : IF1, IF2, IF3
{
// main implementation of MyClass
}
partial class MyClass
{
// implementation of IF1
}
partial class MyClass
{
// implementation of IF2
}
Implements
mot - clé pour indiquer qu'une méthode appartient à une interface)
Mis à part les autres réponses ...
Je les ai trouvés utiles comme tremplin dans la refonte des classes divines. Si une classe a plusieurs responsabilités (surtout s'il s'agit d'un très gros fichier de code), je trouve avantageux d'ajouter 1x classe partielle par responsabilité comme premier passage pour organiser puis refactoriser le code.
Cela aide grandement car il peut aider à rendre le code beaucoup plus lisible sans affecter réellement le comportement d'exécution. Il peut également aider à identifier quand une responsabilité est facile à refactoriser ou est étroitement liée à d'autres aspects.
Cependant - pour être clair - c'est toujours du mauvais code, à la fin du développement, vous voulez toujours une responsabilité par classe ( PAS par classe partielle). C'est juste un tremplin :)
Déclaration de méthode partielle uniquement Même le code est compilé avec la déclaration de méthode uniquement et si l'implémentation de la méthode n'est pas présente, le compilateur peut supprimer ce morceau de code en toute sécurité et aucune erreur de temps de compilation ne se produira.
Pour vérifier le point 4. Créez simplement un projet winform et incluez cette ligne après le constructeur Form1 et essayez de compiler le code
partial void Ontest(string s);
Voici quelques points à considérer lors de l'implémentation de classes partielles: -
Une grande utilité consiste à séparer le code généré du code écrit à la main qui appartient à la même classe.
Par exemple, puisque LINQ to SQL utilise des classes partielles, vous pouvez écrire votre propre implémentation de certaines fonctionnalités (comme les relations plusieurs-à-plusieurs) et ces morceaux de code personnalisé ne seront pas écrasés lorsque vous régénérerez le code.
Il en va de même pour le code WinForms. Tout le code généré par Designer va dans un fichier que vous ne touchez généralement pas. Votre code manuscrit va dans un autre fichier. De cette façon, lorsque vous modifiez quelque chose dans Designer, vos modifications ne sont pas époustouflées.
Il est vrai que la classe partielle est utilisée dans la génération automatique de code, une utilisation peut être de maintenir un fichier de classe volumineux qui peut contenir des milliers de lignes de code. Vous ne savez jamais que votre classe pourrait se retrouver avec 10 000 lignes et vous ne voulez pas créer une nouvelle classe avec un nom différent.
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.
Une autre utilisation possible pourrait être que plusieurs développeurs peuvent travailler sur la même classe car ils sont stockés à différents endroits. Les gens pourraient rire, mais on ne sait jamais que cela peut parfois être difficile.
public partial class Product
{
//you are writing the business logic for fast moving product
}
public partial class Product
{
// Another developer writing some business logic...
}
J'espère que cela a du sens!
Les classes partielles s'étendent sur plusieurs fichiers.
Comment pouvez-vous utiliser le modificateur partiel sur une déclaration de classe C #?
Avec des classes partielles, vous pouvez séparer physiquement une classe en plusieurs fichiers. Cela se fait souvent par des générateurs de code.
Exemple
Avec les classes C # normales, vous ne pouvez pas déclarer une classe dans deux fichiers distincts dans le même projet. Mais avec le partial
modificateur, vous le pouvez.
Ceci est utile si un fichier est généralement édité et que l'autre est généré par la machine ou rarement édité.
Voici un exemple à clarifier:
class Program
{
static void Main()
{
A.A1();
A.A2();
}
}
Contenu du fichier A1.cs: C #
using System;
partial class A
{
public static void A1()
{
Console.WriteLine("A1");
}
}
Contenu du fichier A2.cs: C #
using System;
partial class A
{
public static void A2()
{
Console.WriteLine("A2");
}
}
Production:
A1
A2
Une partie est requise ici.
Si vous supprimez le partial
modificateur, vous obtiendrez une erreur contenant ce texte:
[L'espace de noms '
<global namespace>
' contient déjà une définition pour 'A
'].
Pointe:
Pour résoudre ce problème, vous pouvez utiliser le partial
mot clé ou modifier l'un des noms de classe.
Comment le compilateur C # gère-t-il les classes partielles?
Si vous démontez le programme ci-dessus (en utilisant IL Disassembler), vous verrez que les fichiers A1.cs et A2.cs sont éliminés. Vous constaterez que la classe A est présente.
La classe A contiendra les méthodes A1 et A2 dans le même bloc de code. Les deux classes ont été fusionnées en une seule.
Résultat compilé de A1.cs et A2.cs: C #
internal class A
{
// Methods
public static void A1()
{
Console.WriteLine("A1");
}
public static void A2()
{
Console.WriteLine("A2");
}
}
Sommaire
garder tout aussi propre que possible lorsque vous travaillez avec d'énormes classes, ou lorsque vous travaillez en équipe, vous pouvez modifier sans remplacer (ou toujours valider les modifications)
L'utilisation principale pour les classes partielles est avec le code généré. Si vous regardez le réseau WPF (Windows Presentation Foundation), vous définissez votre interface utilisateur avec le balisage (XML). Ce balisage est compilé en classes partielles. Vous remplissez le code avec des classes partielles de votre choix.
Si vous avez une classe suffisamment grande qui ne se prête pas à une refactorisation efficace, la séparer en plusieurs fichiers permet de garder les choses organisées.
Par exemple, si vous avez une base de données pour un site contenant un forum de discussion et un système de produits, et que vous ne voulez pas créer deux classes de fournisseurs différentes (PAS la même chose qu'une classe proxy, juste pour être clair), vous pouvez créer une seule classe partielle dans différents fichiers, comme
MyProvider.cs - logique de base
MyProvider.Forum.cs - méthodes se rapportant spécifiquement au forum
MyProvider.Product.cs - méthodes pour les produits
C'est juste une autre façon de garder les choses organisées.
En outre, comme d'autres l'ont dit, il s'agit de la seule façon d'ajouter des méthodes à une classe générée sans courir le risque de voir vos ajouts détruits lors de la prochaine régénération de la classe. Cela est pratique avec le code généré par modèle (T4), les ORM, etc.
Comme alternative aux directives de précompilateur.
Si vous utilisez des directives de précompilateur (à savoir #IF DEBUG
), vous vous retrouvez avec un code à l'aspect noueux mélangé à votre code de version réel.
Vous pouvez créer une classe partielle séparée pour contenir ce code, et soit encapsuler la classe partielle entière dans une directive, soit omettre l'envoi de ce fichier de code au compilateur (en faisant de même).
Les références de service sont un autre exemple où les classes partielles sont utiles pour séparer le code généré du code créé par l'utilisateur.
Vous pouvez "étendre" les classes de service sans les écraser lorsque vous mettez à jour la référence de service.
Une autre utilisation que j'ai vue est,
Extension d'une grande classe abstraite concernant la logique d'accès aux données,
j'ai divers fichiers avec des noms 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..
}
La plupart des gens remarquent que cela partial
ne devrait être utilisé que pour une classe qui a un fichier de code généré ou pour les interfaces. Je ne suis pas d'accord et voici pourquoi.
Pour un exemple, regardons la classe C # System.Math ... c'est la classe . Je n'essaierais pas de bourrer plus de 70 méthodes dans le même fichier de code unique. Ce serait un cauchemar à entretenir.
Placer chaque méthode mathématique dans des fichiers de classe partiels individuels et tous les fichiers de code dans un dossier Math du projet serait une organisation nettement plus propre.
La même chose pourrait / resterait vraie pour de nombreuses autres classes qui ont une grande quantité de fonctionnalités diverses. Par exemple, une classe de gestion de l'API PrivateProfile peut bénéficier de sa division en un ensemble propre de fichiers de classe partiels dans un seul dossier de projet.
Personnellement, j'ai également divisé ce que la plupart des gens appellent les classes "auxiliaires" ou "utilitaires" en fichiers partiels individuels pour chaque méthode ou groupe fonctionnel de méthode. Par exemple, sur un projet, la classe d'aide de chaîne a près de 50 méthodes. Ce serait un long fichier de code lourd même en utilisant des régions. Il est beaucoup plus facile de gérer l'utilisation de fichiers de classe partiels individuels pour chaque méthode.
Je serais juste prudent en utilisant des classes partielles et garderais toute la disposition des fichiers de code cohérente tout au long du projet. Par exemple, placer des énumérations publiques de classe et des membres privés de classe dans un fichier Common.cs ou un fichier portant le même nom dans le dossier, au lieu de les répartir sur les fichiers, sauf s'ils ne sont spécifiques qu'au fichier partiel dans lequel ils sont contenus.
Gardez à l'esprit que lorsque vous divisez une classe en fichiers séparés, vous perdez également la possibilité d'utiliser la barre de séparation de l'éditeur de texte qui vous permet de visualiser simultanément deux sections différentes d'un fichier en cours.
Les classes partielles permettent d'ajouter des fonctionnalités à un programme convenablement conçu simplement en ajoutant des fichiers source. Par exemple, un programme d'importation de fichiers pourrait être conçu de manière à ce que l'on puisse ajouter différents types de fichiers connus en ajoutant des modules qui les gèrent. Par exemple, le convertisseur de type de fichier principal peut inclure une petite classe:
Classe publique partielle zzFileConverterRegistrar Registre des événements (ByVal mainConverter as zzFileConverter) Sub registerAll (ByVal mainConverter as zzFileConverter) Registre RaiseEvent (mainConverter) End Sub Fin de classe
Chaque module qui souhaite enregistrer un ou plusieurs types de convertisseur de fichiers peut inclure quelque chose comme:
Classe publique partielle zzFileConverterRegistrar Private Sub RegisterGif (ByVal mainConverter as zzFileConverter) Me gère. mainConverter.RegisterConverter ("GIF", GifConverter.NewFactory)) End Sub Fin de classe
Notez que la classe principale du convertisseur de fichiers n'est pas "exposée" - elle expose simplement une petite classe de stub à laquelle les modules complémentaires peuvent s'accrocher. Il existe un léger risque de conflits de nommage, mais si la routine "register" de chaque module complémentaire est nommée en fonction du type de fichier qu'elle traite, elle ne devrait probablement pas poser de problème. On pourrait coller un GUID au nom du sous-programme d'enregistrement si l'on s'inquiétait de telles choses.
Modifier / Addendum Pour être clair, le but de ceci est de fournir un moyen par lequel une variété de classes séparées peut informer un programme principal ou une classe à leur sujet. La seule chose que le convertisseur de fichiers principal fera avec zzFileConverterRegistrar est d'en créer une instance et d'appeler la méthode registerAll qui déclenchera l'événement Register. Tout module qui veut accrocher cet événement peut exécuter du code arbitraire en réponse à cela (c'est toute l'idée) mais il n'y a rien qu'un module puisse faire en étendant incorrectement la classe zzFileConverterRegistrar autre que de définir une méthode dont le nom correspond à celui d'autre chose . Il serait certainement possible pour une extension mal écrite de casser une autre extension mal écrite, mais la solution pour cela est que quiconque ne veut pas que son extension soit cassée l'écrive simplement correctement.
On pourrait, sans utiliser de classes partielles, avoir un peu de code quelque part dans la classe principale du convertisseur de fichiers, qui ressemblait à:
RegisterConverter ("GIF", GifConvertor.NewFactory) RegisterConverter ("BMP", BmpConvertor.NewFactory) RegisterConverter ("JPEG", JpegConvertor.NewFactory)
mais l'ajout d'un autre module de conversion nécessiterait d'entrer dans cette partie du code du convertisseur et d'ajouter le nouveau convertisseur à la liste. En utilisant des méthodes partielles, ce n'est plus nécessaire - tous les convertisseurs seront inclus automatiquement.
IModule
interface?
IModule
, vous pouvez utiliser un framework de plugin comme MEF (juste un parmi beaucoup d'autres), etc. etc.
Les classes partielles ont récemment aidé au contrôle de code source où plusieurs développeurs ajoutaient à un fichier où de nouvelles méthodes étaient ajoutées dans la même partie du fichier (automatisée par Resharper).
Ces poussées vers git ont provoqué des conflits de fusion. Je n'ai trouvé aucun moyen de dire à l'outil de fusion de prendre les nouvelles méthodes comme un bloc de code complet.
Les classes partielles à cet égard permettent aux développeurs de s'en tenir à une version de leur fichier, et nous pouvons les fusionner plus tard à la main.
exemple -
Depuis MSDN :
1.Au moment de la compilation, les attributs des définitions de type partiel sont fusionnés. Par exemple, considérez les déclarations suivantes:
[SerializableAttribute]
partial class Moon { }
[ObsoleteAttribute]
partial class Moon { }
Ils sont équivalents aux déclarations suivantes:
[SerializableAttribute]
[ObsoleteAttribute]
class Moon { }
Les éléments suivants sont fusionnés à partir de toutes les définitions de type partiel:
Commentaires XML
interfaces
attributs de paramètres de type générique
attributs de classe
membres
2.Une autre chose, les classes partielles imbriquées peuvent également être partielles:
partial class ClassWithNestedClass
{
partial class NestedClass { }
}
partial class ClassWithNestedClass
{
partial class NestedClass { }
}
Voici une liste de certains des avantages des classes partielles.
Vous pouvez séparer le code de conception d'interface utilisateur et le code de logique métier afin qu'il soit facile à lire et à comprendre. Par exemple, vous développez une application Web à l'aide de Visual Studio et ajoutez un nouveau formulaire Web, puis il existe deux fichiers source, "aspx.cs" et "aspx.designer.cs". Ces deux fichiers ont la même classe avec le mot-clé partial. La classe ".aspx.cs" a le code logique métier tandis que "aspx.designer.cs" a la définition du contrôle de l'interface utilisateur.
Lorsque vous travaillez avec une source générée automatiquement, le code peut être ajouté à la classe sans avoir à recréer le fichier source. Par exemple, vous travaillez avec LINQ to SQL et créez un fichier DBML. Maintenant, lorsque vous faites glisser et déposez une table, elle crée une classe partielle dans designer.cs et toutes les colonnes de table ont des propriétés dans la classe. Vous avez besoin de plus de colonnes dans cette table pour vous lier à la grille de l'interface utilisateur, mais vous ne voulez pas ajouter une nouvelle colonne à la table de base de données afin de pouvoir créer un fichier source distinct pour cette classe qui a une nouvelle propriété pour cette colonne et il être une classe partielle. Cela affecte donc le mappage entre la table de base de données et l'entité DBML, mais vous pouvez facilement obtenir un champ supplémentaire. Cela signifie que vous pouvez écrire le code par vous-même sans vous soucier du code généré par le système.
Plusieurs développeurs peuvent simultanément écrire le code de la classe.
Vous pouvez mieux gérer votre application en compactant de grandes classes. Supposons que vous ayez une classe qui possède plusieurs interfaces afin que vous puissiez créer plusieurs fichiers source en fonction des implémentations d'interface. Il est facile de comprendre et de maintenir une interface implémentée sur laquelle le fichier source a une classe partielle.
Chaque fois que j'ai une classe qui contient une classe imbriquée de toute taille / complexité significative, je marque la classe comme partial
et place la classe imbriquée dans un fichier séparé. Je nomme le fichier contenant la classe imbriquée à l'aide de la règle: [nom de classe]. [Nom de classe imbriquée] .cs.
Le blog MSDN suivant explique comment utiliser des classes partielles avec des classes imbriquées pour la maintenabilité: http://blogs.msdn.com/b/marcelolr/archive/2009/04/13/using-partial-classes-with-nested-classes-for- maintenabilité.aspx
Je sais que cette question est vraiment ancienne mais je voudrais juste ajouter mon point de vue sur les cours partiels.
L'une des raisons pour lesquelles j'utilise personnellement des classes partielles est lorsque je crée des liaisons pour un programme, en particulier des machines d'état.
Par exemple, OpenGL est une machine à états, il y a des tas de méthodes qui peuvent toutes être modifiées globalement, cependant, d'après mon expérience, lier quelque chose de similaire à OpenGL où il y a tellement de méthodes, la classe peut facilement dépasser 10k LOC.
Les cours partiels décomposeront cela pour moi et m'aideront à trouver des méthodes rapidement.
Les classes partielles sont principalement introduites pour aider les générateurs de code, donc nous (utilisateurs) ne finissons pas par perdre tous nos travaux / modifications des classes générées comme la classe .designer.cs d'ASP.NET à chaque régénération, presque tous les nouveaux outils qui génèrent code LINQ, EntityFrameworks, ASP.NET utilisent des classes partielles pour le code généré, nous pouvons donc ajouter ou modifier en toute sécurité la logique de ces codes générés en tirant parti des classes et méthodes partielles, mais soyez très prudent avant d'ajouter des éléments au code généré à l'aide de classes partielles c'est plus facile si nous cassons la construction mais pire si nous introduisons des erreurs d'exécution. Pour plus de détails, consultez ce http://www.4guysfromrolla.com/articles/071509-1.aspx
Je note deux usages que je n'ai pas pu trouver explicitement dans les réponses.
Certains développeurs utilisent des commentaires pour séparer les différentes "parties" de leur classe. Par exemple, une équipe peut utiliser la convention suivante:
public class MyClass{
//Member variables
//Constructors
//Properties
//Methods
}
Avec les classes partielles, nous pouvons aller plus loin et diviser les sections en fichiers séparés. Par convention, une équipe peut suffixer chaque fichier avec la section qui lui correspond. Donc, dans ce qui précède, nous aurions quelque chose comme: MyClassMembers.cs, MyClassConstructors.cs, MyClassProperties.cs, MyClassMethods.cs.
Comme d'autres réponses ont fait allusion, la question de savoir s'il vaut la peine de diviser la classe dépend probablement de la taille de la classe dans ce cas. S'il est petit, il est probablement plus facile de tout avoir dans une seule classe de maître. Mais si l'une de ces sections devient trop volumineuse, son contenu peut être déplacé vers une classe partielle distincte, afin de garder la classe principale propre. Une convention dans ce cas pourrait être de laisser un commentaire en disant quelque chose comme "Voir la classe partielle" après le titre de la section, par exemple:
//Methods - See partial class
C'est probablement une occurrence rare, mais il peut y avoir une collision d'espace de noms entre deux fonctions des bibliothèques que vous souhaitez utiliser. Dans une seule classe, vous pouvez tout au plus utiliser une clause using pour l'une d'entre elles. Pour l'autre, vous auriez besoin d'un nom complet ou d'un alias. Avec des classes partielles, puisque chaque espace de noms et chaque liste d'instructions sont différents, on pourrait séparer les deux ensembles de fonctions en deux fichiers distincts.
using Library1 = The.Namespace.You.Need
ouglobal::Root.Of.Namespace