web-dev-qa-db-fra.com

Quand est-il approprié d'utiliser des classes partielles C #?

Je me demandais si quelqu'un pourrait me donner un aperçu des raisons pour lesquelles je les utiliserais et des avantages que j'obtiendrais dans le processus.

474
Asterix

La principale utilisation des classes partielles est de simplifier la vie des générateurs/concepteurs de code. Les classes partielles permettent au générateur d'émettre simplement le code dont ils ont besoin et sans avoir à gérer les modifications apportées au fichier par l'utilisateur. 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 cela est de voir comment les concepteurs fonctionnaient avant les classes partielles. Le concepteur WinForms crachait tout le code à l'intérieur d'une région avec des commentaires fortement formulés sur la non-modification du code. Il a fallu insérer toutes sortes d'heuristiques pour trouver le code généré pour un traitement ultérieur. Désormais, il peut simplement ouvrir le fichier designer.cs et avoir la certitude qu'il ne contient que du code pertinent pour le concepteur.

390
JaredPar

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
}
240
relascope

Mis à part les autres réponses ...

Je les ai trouvés utiles comme point de départ pour la refactorisation des classes divines. Si une classe a plusieurs responsabilités (en particulier s'il s'agit d'un très gros fichier de code), je trouve qu'il est avantageux d'ajouter une classe partielle 1x par responsabilité en tant que premier passage pour organiser et ensuite refactoriser le code.

Cela aide beaucoup car cela peut aider à rendre le code beaucoup plus lisible sans affecter réellement le comportement d'exécution. Cela peut également aider à identifier le moment où une responsabilité est facile à reformuler 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 :)

152
STW
  1. Développeur multiple Utilisation de classes partielles Plusieurs développeurs peuvent travailler sur la même classe facilement.
  2. Générateur de code Les classes partielles sont principalement utilisées par le générateur de code pour séparer les préoccupations
  3. Méthodes partielles À l'aide de classes partielles, vous pouvez également définir des méthodes partielles où un développeur peut simplement définir la méthode et que l'autre développeur peut implémenter.
  4. Déclaration de méthode partielle uniquement Même le code est compilé avec la déclaration de méthode seulement 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 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: -

  1. Utilisez un mot clé partiel dans chaque partie de la classe partielle.
  2. Le nom de chaque partie de la classe partielle doit être identique, mais le nom du fichier source de chaque partie de la classe partielle peut être différent.
  3. Toutes les parties d'une classe partielle doivent être dans le même espace de noms.
  4. Chaque partie d'une classe partielle doit figurer dans le même assembly ou DLL, autrement dit, vous ne pouvez pas créer de classe partielle dans les fichiers source à partir d'un projet de bibliothèque de classes différent.
  5. Chaque partie d'une classe partielle doit avoir la même accessibilité. (c'est-à-dire privé, public ou protégé)
  6. Si vous héritez d'une classe ou d'une interface sur une classe partielle, toutes les parties de cette classe partielle en héritent.
  7. Si une partie d'une classe partielle est scellée, alors toute la classe sera scellée.
  8. Si une partie de la classe partielle est abstraite, la classe entière sera considérée comme une classe abstraite.
78
hellowahab

Une excellente utilisation consiste à séparer le code généré du code manuscrit appartenant à la même classe.

Par exemple, étant donné que LINQ to SQL utilise des classes partielles, vous pouvez écrire votre propre implémentation de certaines fonctionnalités (telles que les relations plusieurs à plusieurs) et ces éléments de code personnalisé ne seront pas écrasés lorsque vous le régénérerez.

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. Ainsi, lorsque vous modifiez quelque chose dans Designer, vos modifications ne sont pas époustouflées.

55
Justin Niessner

Il est vrai que Partial Class est utilisé dans la génération de code automatique. Une utilisation possible consiste à gérer un fichier de classe volumineux pouvant comporter 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 puissent travailler sur la même classe, car ils sont stockés à différents endroits. Les gens peuvent rire mais vous ne savez jamais que cela peut être difficile parfois.

Product1.cs

public partial class Product
{
    //you are writing the business logic for fast moving product
}

Product2.cs

public partial class Product
{
    // Another developer writing some business logic...
}

J'espère que ça a du sens!

19
kausar ahmed

gardez tout aussi propre que possible lorsque vous travaillez avec de grandes classes ou lorsque vous travaillez en équipe, vous pouvez éditer sans modifier (ou toujours valider les modifications)

12
user406871

Les classes partielles couvrent plusieurs fichiers.

How can you use the partial modifier on a C# class declaration?

Avec partial, 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 du même projet.

Mais avec le modificateur partiel, vous pouvez.

Ceci est utile si un fichier est généralement édité et que l'autre est généré par une machine ou rarement édité.

An Example will clear your concept.

class Program
{
    static void Main()
    {
    A.A1();
    A.A2();
    }
}

//Contents of file A1.cs: C#

using System;

partial class A
{
    public static void A1()
    {
    Console.WriteLine("A1");
    }
}

//Contents of file A2.cs: C#

using System;

partial class A
{
    public static void A2()
    {
    Console.WriteLine("A2");
    }
}

Output

A1
A2

Partielle est nécessaire ici.

If you remove the partial modifier, you will get an error containing this text: [The namespace '<global namespace>' already contains a definition for 'A'].

Astuce: Pour résoudre ce problème, vous pouvez utiliser le mot-clé partial ou modifier l'un des noms de classe.

How does the C# compiler deal with partial classes?

Si vous démontez le programme ci-dessus, vous constaterez que les fichiers A1.cs et A2.cs sont éliminés.

Vous constaterez que la classe A est présente.

Désassembleur IL Ainsi: 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");
    }
}

Résumé

Les classes partielles peuvent simplifier certaines situations de programmation C #.

Ils sont souvent utilisés dans Visual Studio lors de la création de programmes Windows Forms/WPF.

Le code C # généré par la machine est séparé.

Ou vous pouvez trouver la description complète ici .

11
Vivek Saurav

L'utilisation principale des classes partielles est avec le code généré. Si vous examinez le réseau WPF (Windows Presentation Foundation), vous définissez votre interface utilisateur avec un balisage (XML). Ce balisage est compilé en classes partielles. Vous remplissez le code avec des classes partielles de votre choix.

11
cletus

Si vous avez une classe suffisamment grande qui ne se prête pas à une refactorisation efficace, séparez-la en plusieurs fichiers aide à 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 de proxy, pour être clair), vous pouvez créer une seule classe partielle dans différents fichiers, comme

MyProvider.cs - la logique de base

MyProvider.Forum.cs - méthodes spécifiques 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 déjà dit, il s'agit du seul moyen 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. Ceci est pratique avec un code généré par un modèle (T4), des ORM, etc.

8
3Dave

Comme alternative aux directives de pré-compilation.

Si vous utilisez des directives de pré-compilateur (à savoir #IF DEBUG]), vous vous retrouvez avec un code très grossier mêlé à votre code de version actuel.

Vous pouvez créer une classe partielle séparée contenant ce code et envelopper la classe entière dans une directive ou en omettant que ce fichier-code soit envoyé au compilateur (il en va de même).

7
STW

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.

6

Une autre utilisation que j'ai vu est,

L'extension d'une grande classe abstraite concernant la logique d'accès aux données,

j'ai divers fichiers avec les 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..
}

Les classes partielles permettent d'ajouter des fonctionnalités à un programme bien conçu simplement en ajoutant des fichiers source. Par exemple, un programme d'importation de fichier pourrait être conçu de manière à pouvoir ajouter différents types de fichiers connus en ajoutant des modules qui les gèrent. Par exemple, le convertisseur de type de fichier principal pourrait inclure une petite classe:

Registre d'événements partiel de la classe publique zzFileConverterRegistrar 
 (ByVal mainConverter en tant que zzFileConverter) 
 Sub registerAll (ByVal mainConverter en tant que zzFileConverter) 
 RaiseEvent Register (mainConverter) 
 End Sub 
 Classe finale

Chaque module qui souhaite enregistrer un ou plusieurs types de convertisseur de fichier peut inclure quelque chose comme:

 Classe publique partielle zzFileConverterRegistrar 
 Private Sub RegisterGif (ByVal mainConverter en tant que zzFileConverter) gère Me.Register 
 MainConverter.RegisterConverter ("GIF", GifConverter.NewFactory) 
. End Sub 
 End Class 

Notez que la classe de convertisseur de fichier principale n'est pas "exposée" - elle expose simplement une petite classe de stub à laquelle les modules de complément peuvent se connecter. Il existe un léger risque de conflits de noms, mais si la routine "register" de chaque module complémentaire est nommée en fonction du type de fichier traité, elle ne devrait probablement pas poser de problème. On pourrait coller un GUID au nom du sous-programme d'enregistrement si on s'inquiétait de ce genre de choses.

Editer/Addendum Pour être clair, l'objectif est de fournir un moyen par lequel une variété de classes séparées peut en informer un programme principal ou une classe. La seule chose que le convertisseur de fichier principal fera avec zzFileConverterRegistrar est d’en créer une instance et d’appeler la méthode registerAll qui déclenche l’événement Register. Tout module qui souhaite accrocher cet événement peut exécuter du code arbitraire en réponse (c'est l'idée même), mais il n'y a rien qu'un module puisse faire en étendant de manière incorrecte la classe zzFileConverterRegistrar autre que de définir une méthode dont le nom correspond à autre chose. . Il serait certainement possible pour une extension mal écrite de casser une autre extension mal écrite, mais la solution à 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 fichier, qui ressemblait à:

 RegisterConverter ("GIF", GifConvertor.NewFactory) 
 RegisterConverter ("BMP", BmpConvertor.NewFactory) 
 RegisterConverter ("JPEG", JpegConvertor.NewFactory) 
.

mais pour ajouter un autre module de convertisseur, il faudrait entrer dans cette partie du code du convertisseur et ajouter le nouveau convertisseur à la liste. En utilisant des méthodes partielles, ce n'est plus nécessaire - tous les convertisseurs seront inclus automatiquement.

4
supercat

La plupart des gens remarquent que partial ne devrait être utilisé que pour une classe qui a un fichier de code généré ou pour des interfaces. Je ne suis pas d'accord, et voici pourquoi.

Pour un exemple, regardons la classe C # System.Math ... c'est class. Je n'essaierais pas de ranger plus de 70 méthodes dans le même fichier de code. 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 constituerait une organisation nettement plus propre.

La même chose pourrait/serait valable pour de nombreuses autres classes qui ont une grande quantité de fonctionnalités diverses. Par exemple, une classe de gestion de l'API PrivateProfile pourrait tirer avantage d'une division en un ensemble propre de fichiers de classe partiels dans un seul dossier de projet.

Personnellement, je sépare également ce que la plupart des gens appellent les classes "helper" ou "utility" en fichiers partiels individuels pour chaque méthode ou groupe fonctionnel de méthode. Par exemple, sur un projet, la classe string helper a près de 50 méthodes. Ce serait un fichier de code long et lourd, même en utilisant des régions. Il est beaucoup plus facile de gérer en utilisant des fichiers de classe partiels individuels pour chaque méthode.

Je ferais simplement attention en utilisant des classes partielles et garderais toute la disposition des fichiers de code cohérente tout au long du projet. Par exemple, placer tous les enums publics de la classe et les membres privés de la classe dans un fichier Common.cs ou de nom similaire dans le dossier, au lieu de les répartir dans les fichiers, à moins qu'ils ne soient spécifiques au fichier partiel dans lequel ils sont contenus.

Gardez à l'esprit que lorsque vous divisez une classe en plusieurs fichiers, vous perdez également la possibilité d'utiliser la barre de division de l'éditeur de texte qui vous permet d'afficher simultanément deux sections différentes d'un fichier en cours.

3
deegee

De MSDN :

1.Au moment de la compilation, les attributs des définitions de type partiel sont fusionnés. Par exemple, considérons 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ètre de type générique

  • attributs de classe

  • membres

2. Une autre chose, les classes partielles imbriquées peuvent être aussi partielles:

partial class ClassWithNestedClass
{
    partial class NestedClass { }
}

partial class ClassWithNestedClass
{
    partial class NestedClass { }
}
3
Eli

Des classes partielles ont récemment contribué au contrôle de la source lorsque plusieurs développeurs ont été ajoutés à un fichier dans lequel de nouvelles méthodes ont été ajoutées dans la même partie du fichier (automatisée par Resharper).

Ces poussées à git ont provoqué des conflits de fusion. Je n'ai trouvé aucun moyen de demander à 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 ultérieurement ultérieurement manuellement.

exemple -

  • MainClass.cs - contient les champs, le constructeur, etc.
  • MainClass1.cs - un nouveau code de développement pour les développeurs
  • MainClass2.cs - est une autre classe de développeurs pour leur nouveau code.
3
Jay

Voici une liste de certains des avantages des classes partielles.

Vous pouvez séparer le code de conception de l'interface utilisateur et le code de la logique métier afin de faciliter la lecture et la compréhension. Par exemple, vous développez une application Web à l'aide de Visual Studio et ajoutez un nouveau formulaire Web, puis deux fichiers sources, "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 de la logique applicative, alors que "aspx.designer.cs" a la définition du contrôle d'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 utilisez LINQ to SQL et créez un fichier DBML. Désormais, lorsque vous faites glisser une table, elle crée une classe partielle dans designer.cs et toutes les colonnes de la table ont des propriétés dans la classe. Vous avez besoin de plus de colonnes dans cette table pour 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 séparé pour cette classe qui possède une nouvelle propriété pour cette colonne. ê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 vous-même sans vous occuper du code généré par le système.

Plusieurs développeurs peuvent écrire simultanément 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.

1
shashi

Je sais que cette question est vraiment ancienne mais je voudrais juste ajouter mon point de vue sur les cours partiels.

Personnellement, j'utilise personnellement des classes partielles lorsque je crée des liaisons pour un programme, en particulier des machines à états.

Par exemple, OpenGL est une machine à états, il y a tas de méthodes qui peuvent toutes être changées globalement, cependant, dans mon expérience, reliant quelque chose de similaire à OpenGL où il y a tant de méthodes, la classe peut facilement dépasser 10k LOC.

Les classes partielles décomposeront cela pour moi et m'aidera à trouver des méthodes rapidement.

1
user6630825

Chaque fois que j'ai une classe qui contient une classe imbriquée de taille/complexité significative, je la marque en tant que partial et je la place dans un fichier séparé. Je nomme le fichier contenant la classe imbriquée en utilisant la règle: [nom de la classe]. [Nom de la classe imbriquée] .cs.

Le blog MSDN suivant explique l'utilisation des classes partielles avec des classes imbriquées à des fins de maintenabilité: http://blogs.msdn.com/b/marcelolr/archive/2009/04/13/using-partial-classes-with-nested- classes-for-maintenability.aspx

1
Ɖiamond ǤeezeƦ

Les classes partielles sont principalement introduites pour aider les générateurs de code. Ainsi, nous (utilisateurs) ne perdons pas tous nos travaux/modifications des classes générées telles que la classe .designer.cs d'ASP.NET chaque fois que nous régénérons, presque tous les nouveaux outils qui génèrent code LINQ, EntityFrameworks, ASP.Net Utilisez des classes partielles pour le code généré, afin que nous puissions ajouter ou modifier en toute sécurité la logique de ces codes générés en tirant parti des classes et méthodes Partial, mais soyez très prudent avant d'ajouter des éléments au code généré à l'aide de classes Partial C'est plus facile si nous cassons la construction, mais pire si nous introduisons des erreurs d'exécution. Pour plus de détails, vérifiez ceci http://www.4guysfromrolla.com/articles/071509-1.aspx

0
Kiran Bheemarti