2012-02-08 3 views
15

У меня есть два варианта в VS2010 для реализации интерфейсов.Внедрить интерфейс и реализовать интерфейс Явно в C#

enter image description here

Когда у меня есть интерфейс IHelper.cs следующим образом:

public interface IHelper 
    .... 
    IEnumerable<IPort> Ports { get; } 

"Реализовать интерфейс Явное" дает этот код:

IEnumerable<IPort> IHelper.Ports 
    { 
     get 
     { 
      ... 
     } 
    } 

И "Реализовать интерфейс" дает мне этот код:

public IEnumerable<IPort> Ports 
    { 
     get 
     { 
      ... 
     } 
    } 

Являются ли они такими же или разными? Почему у меня есть два варианта реализации интерфейсов в C#?

+0

Было бы «реализовать публичный интерфейс» и «реализовать частный интерфейс» было слишком сложно? – PRMan

ответ

24

Явные декларации интерфейса означают, что члены интерфейса недоступны для типов, отличных от самого интерфейса, поэтому реализации типов необходимо будет отнести к интерфейсу до их публичного доступа.

Неявный стандартный способ реализации большинства интерфейсов предоставляет элементы интерфейса в публичном API-интерфейсе разработчика.

Основная причина, по которой заключается в явных определениях интерфейсов, заключается в том, чтобы избежать конфликтов имен, если вы реализуете два интерфейса, которые содержат методы с одной и той же сигнатурой ... явное определение позволяет компилятору поддерживать достаточно четкие сигнатуры для разрешения.

Вторая причина, по которой в комментариях предлагается поддержка кода, как предложено XenoPuTtSs, заключается в том, что явные определения будут вызывать ошибки компилятора для типов реализации, если подпись метода удалена. При неявных реализациях удаление метода из интерфейса оставит этот метод в качестве регулярного члена любого типа - это означает, что вам нужно искать вручную в настоящее время недействительные реализации методов.

+2

(что не является основной причиной) при изменении интерфейса (например, при удалении или изменении метода) компилятор будет вызывать ошибку для классов, которые явно определяют интерфейсы, потому что эти методы больше не находятся на интерфейсе. Это полезный способ (IMHO) для поиска неиспользуемого кода из крупных проектов. – XenoPuTtSs

+0

@XenoPuTtSs Хорошая мысль, я внесла поправки в свой ответ, чтобы включить это. –

5

Класс, который реализует интерфейс, может явно реализовать элемент этого интерфейса. Когда элемент явно реализован, к нему нельзя получить доступ через экземпляр класса, но только через экземпляр интерфейса.

// explicit1.cs 
interface IDimensions 
{ 
    float Length(); 
    float Width(); 
} 

class Box : IDimensions 
{ 
    float lengthInches; 
    float widthInches; 

public Box(float length, float width) 
{ 
    lengthInches = length; 
    widthInches = width; 
} 
// Explicit interface member implementation: 
float IDimensions.Length() 
{ 
    return lengthInches; 
} 
// Explicit interface member implementation: 
float IDimensions.Width() 
{ 
    return widthInches;  
} 

public static void Main() 
{ 
    // Declare a class instance "myBox": 
    Box myBox = new Box(30.0f, 20.0f); 
    // Declare an interface instance "myDimensions": 
    IDimensions myDimensions = (IDimensions) myBox; 
    // Print out the dimensions of the box: 
    /* The following commented lines would produce compilation 
    errors because they try to access an explicitly implemented 
    interface member from a class instance:     */ 
    //System.Console.WriteLine("Length: {0}", myBox.Length()); 
    //System.Console.WriteLine("Width: {0}", myBox.Width()); 
    /* Print out the dimensions of the box by calling the methods 
    from an instance of the interface:       */ 
    System.Console.WriteLine("Length: {0}", myDimensions.Length()); 
    System.Console.WriteLine("Width: {0}", myDimensions.Width()); 
} 
} 

Явная реализация интерфейса позволяет программисту наследовать два интерфейса, которые разделяют одни и те же имена элементов и дать каждому члену интерфейсного отдельную реализации. В этом примере отображаются размеры окна как в метрических, так и в английских единицах. Класс Box наследует два интерфейса IEnglishDimensions и IMetricDimensions, которые представляют собой различные измерительные системы. Оба интерфейса имеют одинаковые имена элементов, длина и ширина.

взгляд на примере

// explicit2.cs 
// Declare the English units interface: 
interface IEnglishDimensions 
{ 
    float Length(); 
    float Width(); 
} 
// Declare the metric units interface: 
interface IMetricDimensions 
{ 
    float Length(); 
    float Width(); 
} 
// Declare the "Box" class that implements the two interfaces: 
// IEnglishDimensions and IMetricDimensions: 
class Box : IEnglishDimensions, IMetricDimensions 
{ 
    float lengthInches; 
    float widthInches; 
public Box(float length, float width) 
    { 
    lengthInches = length; 
    widthInches = width; 
    } 
// Explicitly implement the members of IEnglishDimensions: 
float IEnglishDimensions.Length() 
{ 
    return lengthInches; 
} 
float IEnglishDimensions.Width() 
{ 
    return widthInches;  
} 
// Explicitly implement the members of IMetricDimensions: 
float IMetricDimensions.Length() 
{ 
    return lengthInches * 2.54f; 
} 
float IMetricDimensions.Width() 
{ 
    return widthInches * 2.54f; 
} 
public static void Main() 
{ 
    // Declare a class instance "myBox": 
    Box myBox = new Box(30.0f, 20.0f); 
    // Declare an instance of the English units interface: 
    IEnglishDimensions eDimensions = (IEnglishDimensions) myBox; 
    // Declare an instance of the metric units interface: 
    IMetricDimensions mDimensions = (IMetricDimensions) myBox; 
    // Print dimensions in English units: 
    System.Console.WriteLine("Length(in): {0}", eDimensions.Length()); 
    System.Console.WriteLine("Width (in): {0}", eDimensions.Width()); 
    // Print dimensions in metric units: 
    System.Console.WriteLine("Length(cm): {0}", mDimensions.Length()); 
    System.Console.WriteLine("Width (cm): {0}", mDimensions.Width()); 
} 
} 

для получения более подробной информации смотрите на этом article

+1

Лучше всего включить в статью ответную информацию из статьи в самом ответе, ссылки непостоянны и могут не дожидаться ответа. Если бы эта ссылка не сработала, ваш ответ не помог бы. –

+0

да я с тобой. – Serghei

6

Они совершенно разные. Если вы реализуете интерфейсы явно, вы сможете ссылаться на члены интерфейса только по ссылке этого интерфейса. Следующий код демонстрирует эту идею.

public interface IFoo { 
    String Bar { get; set; } 
} 
public class ImplicitFoo : IFoo { 
    public string Bar {get;set;} 
} 
public class ExplicitFoo : IFoo { 
    private String _Bar; 
    string IFoo.Bar { 
     get { 
      return _Bar; 
     } 
     set { 
      _Bar = value; 
     } 
    } 
} 
public class Test { 
    public void Test() { 
     var iml = new ImplicitFoo(); 
     // Works fine 
     Console.WriteLine(iml.Bar); 
     var expl = new ExplicitFoo(); 
     var fooInterface = (IFoo)expl; 
     // Works fine 
     Console.WriteLine(fooInterface.Bar); 
     // Throws compile time exception 
     Console.WriteLine(expl.Bar); 
    } 
} 
Смежные вопросы