Как расширить интерфейс, сохранив имена методов? - PullRequest
3 голосов
/ 22 января 2012

Имеется два интерфейса:

interface I1 {
    int Foo();
}

interface I2 {
    void Foo();
}

А класс:

class Test : I1, I2 {
    int I1.Foo() {
        Console.WriteLine("I1.Foo");
        return default(int);
    }

    public void Foo() {
        Console.WriteLine("I2.Foo");
    }
}

Как расширить интерфейс I2 с помощью I1, сохранив методы с именем Foo?

Я попробовал следующий код, но он не компилируется:

interface I1 {
    int Foo();
}

interface I2 : I1 {
    void I2.Foo();
} 

class Test : I2 { /* same code */ }

Ответы [ 3 ]

18 голосов
/ 22 января 2012

В примере неясно, что явное объявление I2.Foo() в самом интерфейсе будет выполнено, если это будет разрешено. Спецификация (с. 13.4.1) позволяет структуре или классу, реализующему интерфейс, объявлять явную реализацию члена. (Интерфейсы не могут объявлять какую-либо реализацию, явную или нет).

Итак, предположим, что мы определили:

interface IFoo
{
    void Bar();
}

interface IBaz : IFoo
{
    new void Bar();
}

interface IQux : IBaz { }

class A : IQux // equivalent to class A : IQux, IBaz, IFoo (spec sec. 13.4.6)
{
    void IFoo.Bar()
    {
        Console.WriteLine("IFoo.Bar");
    }

    void IBaz.Bar()
    {
        Console.WriteLine("IBaz.Bar");
    }

    public void Bar()
    {
        Console.WriteLine("A.Bar");
    }

    // Not allowed: void IQux.Bar() {...}
    // Since "The fully-qualified name of the interface member
    // must reference the interface in which the member
    // was declared" (s. 13.4.1)
}

Тогда следующий драйвер показывает эффект явной реализации метода интерфейса.

public static void Main()
{
    A a = new A();
    a.Bar(); // prints A.Bar
    (a as IFoo).Bar(); // prints IFoo.Bar
    (a as IBaz).Bar(); // prints IBaz.Bar
    (a as IQux).Bar(); // prints IBaz.Bar
}
2 голосов
/ 22 января 2012

не совсем уверен, что вы хотите, чтобы он делал, но вы можете сделать: -

public interface I1
{
    int Foo();
}

public interface I2:I1
{
    new void Foo();
}
0 голосов
/ 22 января 2012

Это работает, только если два метода имеют разную сигнатуру, что означает, что они должны иметь разное количество параметров или разные типы параметров или оба.

Почему бы не назвать два ваших метода GetFoo и DoFoo?

Это будет работать

public interface I1 
{ 
    int Foo(); 
} 

public interface I2 : I1 
{ 
    void Foo(int i); 
} 

Это также будет работать

public interface I1 
{ 
    int GetFoo(); 
} 

public interface I2 : I1 
{ 
    void DoFoo(); 
} 

Вы также можете объявить свойство. Свойства состоят из двух методов: геттер и сеттер.

public interface I
{
    int Foo { get; set; }
}

public class C : I
{
    private int _foo;
    public int Foo
    {
        get {
            // getter
            return _foo;
        }
        set {
            // setter
            _foo = value;
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...