C# 2.0 avait introduit la notion de classe partielle qui permet de fractionner une classe en plusieurs parties mais cette évolution ne concerne pas uniquement les classes car vous pouvez faire de même avec les structures et les interfaces. Grâce au mot clé « partial », il devenait donc possible de déclarer une classe dans un fichier et compléter cette même classe dans un autre fichier. D’ailleurs, cette technique des classes partielles est allègrement utilisée avec les designers (Windows Forms, DataSet, Linq to SQL, etc).

Depuis C# 3.0, il est possible d’aller plus loin en profitant de cette notion des partielles au niveau des méthodes.

Comme je vous le disais, les classes partielles existent depuis C# 2.0 et en voici donc un exemple tout simple :

namespace PartialClassExample
{
    public partial class Product
    {
        private int m_Id = 0;
        private string m_Name = null;

        private void Initialize()
        {
            m_Id = 1;
            m_Name = « Canard en plastique »;
        }
    }

    public partial class Product
    {
        public void DisplayProduct()
        {
            Initialize();
            Console.WriteLine(m_Id +  » –  » + m_Name);
        }
    }
}

Comme vous pouvez le voir, mes deux classes partielles n’en représente qu’une seule, d’ailleurs lors de la compilation, le compilateur s’occupera de fusionner ces deux fractions de classe en une et même classe.

Cette technique s’avère extrêmement utile avec le code généré par les designers car tout ce qui est fait au travers d’un designer est répercuté dans une classe partielle créée dans un fichier (la plupart du temps appelé xxx.Designer.cs). Si le développeur désire ajouter des fonctionnalités à cette classe, il en aura tout à fait la possibilité en créant un nouveau fichier où il pourra continuer le développement de cette classe partielle.

Mais depuis C# 3.0, la notion des partiels s’est étendue aux méthodes. Le but ici est d’avoir d’un côté des méthodes partielles permettant de définir la signature de chacune et de l’autre côté ces mêmes méthodes avec leur implémentation. Autant vous le dire tout de suite, ceci ne sera évidemment possible que dans des classes partielles. En voici un exemple :

namespace PartialClassExample
{
    public partial class Product
    {
        private int m_Id = 0;
        private string m_Name = null;

        partial void onProductChanged();

        public string Name
        {
            get { return m_Name; }
            set
            {
                m_Name = value;
                onProductChanged();
            }
        }
    }

    public partial class Product
    {
        partial void onProductChanged()
        {
            Console.WriteLine(« Le produit a changé ! »);
        }
    }
}

Tout comme pour les classes partielles, on retrouve le mot clé « partial ». La première classe partielle va se contenter de déclarer la méthode partielle « onProductChanged », sans pour autant définir le corps de cette méthode. C’est dans la seconde classe partielle que l’on va retrouver l’implémentation de cette méthode.

Comme vous pouvez le voir aussi, la première classe partielle appelle la méthode « onProductChanged ». Si nous n’avions pas défini d’implémentation à cette méthode, le compilateur aurait optimisé le code pour effacer toute trace de cette méthode qui ne sert dans ce cas là plus à rien.

Cependant, les méthodes partielles sont soumises à quelques règles qu’il ne faut pas oublier :

  • Une méthode partielle doit commencer par le mot clé « partial »
  • Une méthode partielle doit retourner « void »
  • Il est possible d’utiliser le mot clé « ref » pour un paramètre mais pas « out »
  • Une méthode partielle est implicitement privée, elle ne peut donc pas être virtuelle
  • Une méthode partielle ne peut pas être externe
  • Une méthode partielle peut être marquée comme étant « static » ou « unsafe »
  • Une méthode partielle peut être générique
  • Il n’est pas possible de créer un délégué à une méthode partielle