web-dev-qa-db-fra.com

Erreur de compilation: «Le modificateur« public »n'est pas valide pour cet élément» lors de l'implémentation explicite de l'interface

J'obtiens cette erreur lors de la création d'une méthode public sur une classe pour implémenter explicitement le interface. J'ai une solution: en supprimant l'implémentation explicite de la méthode PrintName. Mais je suis surpris de la raison pour laquelle j'obtiens cette erreur.

Quelqu'un peut-il expliquer l'erreur?

Code pour la bibliothèque:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Test.Lib1
{

    public class Customer : i1 
    {
        public string i1.PrintName() //Error Here...
        {
            return this.GetType().Name + " called from interface i1";
        }
    }

    public interface i1
    {
        string PrintName();
    }

    interface i2
    {
        string PrintName();
    }
}

Code pour l'application de test de console:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Test.Lib1;

namespace ca1.Test
{
    class Program
    {
        static void Main(string[] args)
        {
            Customer customer = new Customer();
            Console.WriteLine(customer.PrintName());

            //i1 i1o = new Customer();
            //Console.WriteLine(i1o.printname());

            //i2 i2o = new Customer();
            //Console.WriteLine(i2o.printname());

        }
    }
}
57
Lalit

Lors de l'utilisation de l'implémentation explicite d'une interface, les membres sont forcés à quelque chose de plus restreint que private dans la classe elle-même. Et lorsque le modificateur d'accès est forcé, vous ne pouvez pas en ajouter un.

De même, dans l'interface elle-même, tous les membres sont public. Si vous essayez d'ajouter un modificateur à l'intérieur d'une interface, vous obtiendrez une erreur similaire.

Pourquoi les membres explicites sont-ils (très) privés? Considérer:

interface I1 { void M(); }
interface I2 { void M(); }

class C : I1, I2
{
    void I1.M() { ... }
    void I2.M() { ... }
}

C c = new C();
c.M();         // Error, otherwise: which one?
(c as I1).M(); // Ok, no ambiguity. 

Si ces méthodes étaient publiques, vous auriez un conflit de noms qui ne peut pas être résolu par les règles de surcharge normales.

Pour la même raison, vous ne pouvez même pas appeler M() depuis l'intérieur d'un membre class C. Vous devrez d'abord transtyper this vers une interface spécifique pour éviter la même ambiguïté.

class C : I1, I2
{
   ...
   void X() 
   {  
     M();             // error, which one? 
     ((I1)this).M();  // OK 
   }
}
71
Henk Holterman

http://msdn.Microsoft.com/en-us/library/aa288461 (VS.71) .aspx : Lorsqu'un membre est implémenté explicitement, il n'est pas accessible via une instance de classe, mais uniquement via une instance de l'interface.

Customer customer = new Customer();

Console.WriteLine(customer.PrintName());

Violent cela

11
hackerhasid

Vous ne pouvez pas utiliser de modificateurs d'accès lors de l'implémentation explicite de l'interface. Le membre sera lié à l'interface de toute façon, il n'est donc pas nécessaire de spécifier le modificateur d'accès, car tous les membres de l'interface sont toujours publics, tous les membres explicitement implémentés ne sont accessibles que via un membre de type interface (voir la réponse de statichippo par exemple).

7
Andrew Bezzub