C#인터페이스가 있습니다.암시적 구현에 대 명시적으로 구현

StackOverflow https://stackoverflow.com/questions/143405

  •  02-07-2019
  •  | 
  •  

문제

의 차이점이 무엇인 구현에서 인터페이스 암시적으로명시적으로 C#?

을 사용해야 하는 암시적 및을 사용해야 하는 명시적으?

은 거기에 어떤 장점 및/또는 단점 중 하나 또는 다른?


마이크로소프트의 공식 지침(에서 첫 번째 에디션 Design Guidelines)국 를 사용하여 명시적인 구현에는 권장하지 않음, 이후,그것은 코드에 예기치 않은 행동을 했다.

내 생각에 이 지침은 매우 에서 유효한 pre-IoC 간, 할 때 통과하지 않는 것으로 인터페이스가 있습니다.

할 수 있었을 터치하는 측면뿐만 아니?

도움이 되었습니까?

해결책

암시적 가를 정의할 때 인터페이스를 통해 구성원에서 당신의 클래스입니다. 명시적 은을 정의할 때는 방법에서 당신의 클래스에서 인터페이스입니다.나는 소리를 혼란을 하지만 여기에 내가 무엇을 의미한다: IList.CopyTo 것을 암시적으로 구현으로:

public void CopyTo(Array array, int index)
{
    throw new NotImplementedException();
}

과적으로:

void ICollection.CopyTo(Array array, int index)
{
    throw new NotImplementedException();
}

차이 되는 암시적으로 액세스할 수 있을 통해 귀하의 클래스를 만들면 그것은 주로 해당 클래스뿐만 아니라우 캐스팅으로 인터페이스입니다.명시적으로 구현할 수 있에 액세스할 수 있는 유일한 경우 캐스팅으로 인터페이스 자체.

MyClass myClass = new MyClass(); // Declared as concrete class
myclass.CopyTo //invalid with explicit
((IList)myClass).CopyTo //valid with explicit.

내가 사용하여 명시적을 유지하기 위해 주로 구현를 정리하거나 필요로 할 때 두 가지의 구현이 있습니다.하지만 상관없이 거의 그것을 사용합니다.

나는 확실히 더 많은 그것을 사용 하는 이유/그것을 사용하지 않는 다른 사람에 게시할 것입니다.

다음 게시물 이 스레드에서 뛰어난 뒤에는 각.

다른 팁

암시적 정의 것을 추가하는 방법/등록,등등.요구에 의해 직접 인터페이스 클래스로 공개 방법이 있습니다.

이 명시적으로 정의 힘은 구성원에 노출되는 경우에만 작업을 직접 인터페이스,그리고 근본적인 구현합니다.이는 자주 사용되는 대부분의 경우에 있습니다.

  1. 작업에 의해 직접 인터페이스에,당신은 당신을 인정하지 않, 그리고 연결하는 코드를 기본 구현합니다.
  2. 이벤트에서 당신은 이미 있고,말하는,공공 시설에 이름 코드고 구현하려는 인터페이스는 또한 이름을 제공하고,명시적으로 유지합니다 두 가지 별개입니다.도 만약 그들이 같은 일을 하는데 여전히는 대리자의 명시적 전화을 이름을 제공합니다.당신은 결코 알고,당신을 변경할 수 있습니다 어떻게 이름은 작품에 대한 정상적인 클래스고 어떻게 이름,이 인터페이스 속 작동합니다.
  3. 을 구현하면 인터페이스를 암시적으로 다음의 클래스는 지금 노출 새로운 행동을 수 있는만 관련하여 클라이언트의 인터페이스와 그것이 의미하지 않을 유지하는 간결한 클래스 충분한(내 생각).

외에도 훌륭한 답변이 이미 제공된 경우가 있는 명시적인 구현에 필요한 컴파일러를 알 수있는 무엇이 필요합니다.살펴보 IEnumerable<T> 표적인 예로는 것이 상당히 많습니다.

예를 들어 다음과 같습니다.

public abstract class StringList : IEnumerable<string>
{
    private string[] _list = new string[] {"foo", "bar", "baz"};

    // ...

    #region IEnumerable<string> Members
    public IEnumerator<string> GetEnumerator()
    {
        foreach (string s in _list)
        { yield return s; }
    }
    #endregion

    #region IEnumerable Members
    IEnumerator IEnumerable.GetEnumerator()
    {
        return this.GetEnumerator();
    }
    #endregion
}

여기서, IEnumerable<string> 를 구현하는 IEnumerable, 따라서,우리가 필요한다.그러나 걸어서 모두 일반적이고 일반 버전 모두 구현하는 기능은 같은 방법으로 서명 (C#무시하 돌아 유형을 위해 이).이것은 완전히 합법적이고 괜찮습니다.어떻게 해결하는 컴파일러를 사용합니까?그것은 당신을 뿐만 아니라,대부분에서,하나 암시적 정의를,그것을 해결할 수 있 그것이 무엇을 주시기 바랍니다.

ie.

StringList sl = new StringList();

// uses the implicit definition.
IEnumerator<string> enumerableString = sl.GetEnumerator();
// same as above, only a little more explicit.
IEnumerator<string> enumerableString2 = ((IEnumerable<string>)sl).GetEnumerator();
// returns the same as above, but via the explicit definition
IEnumerator enumerableStuff = ((IEnumerable)sl).GetEnumerator();

PS:작은 조각의 간접에서 명시적인에 대한 정의를페이 작동하기 때문에 함수 안에 있는 컴파일러를 알고 있는 실제적인 type 의 변수가 StringList,그리고 어떻게 확인 함수 호출합니다.멋진 작은 사실을 구현하기 위한 일부의 추상화 계층의 일부.순 코어 인터페이스를 보일 수 있습니다.

이#1

내가 사용하는 경향이 명시적 인터페이스 구현을 억제하"프로그램을 구현"(설계 원리에서 디자인 패턴).

예를 들어, MVP기반한 웹 응용 프로그램:

public interface INavigator {
    void Redirect(string url);
}

public sealed class StandardNavigator : INavigator {
    void INavigator.Redirect(string url) {
        Response.Redirect(url);
    }
}

이제 또 다른 클래스(예: 발표자 에)적게 가능성에 달려 StandardNavigator 구현하고 더 많은 가능성에 달려 INavigator 인터페이스(이후 구현해야하는 것으로 캐스팅될 인터페이스을 사용하여 방식의 Redirect).

이#2

또 다른 이유는 내가 갈 수 있으로 명시적인 인터페이스를 구현할 수 있는 클래스의"기본"인터페이스 청소기입니다.예를 들어,if I were 개발 ASP.NET 서버 제어,내가 원하는 두 개의 인터페이스:

  1. 클래스의 기본 인터페이스에 의해 사용되는 웹 페이지자;고
  2. "숨겨진"인터페이스에 의해 사용되는 발표자는 개발을 처리하 제어 로직

간단한 예제는 다음과 같습니다.그것은 콤보 박스 제어 목록을 고객입니다.이 예제에서,웹 페이지의 개발에 관심이 없을 채우 목록대신,그들은 단지 선택할 수 있도록 고객에 의해 GUID 또는 얻을 선택한 고객의 GUID.발표자를 채웁 상자에서 첫 번째 페이지 로드 및 이 발표자 캡슐화에 의해 제어합니다.

public sealed class CustomerComboBox : ComboBox, ICustomerComboBox {
    private readonly CustomerComboBoxPresenter presenter;

    public CustomerComboBox() {
        presenter = new CustomerComboBoxPresenter(this);
    }

    protected override void OnLoad() {
        if (!Page.IsPostBack) presenter.HandleFirstLoad();
    }

    // Primary interface used by web page developers
    public Guid ClientId {
        get { return new Guid(SelectedItem.Value); }
        set { SelectedItem.Value = value.ToString(); }
    }

    // "Hidden" interface used by presenter
    IEnumerable<CustomerDto> ICustomerComboBox.DataSource { set; }
}

발표자를 채우는 데이터 소스와 웹 페이지 개발 필요가 없을 알고 있어야의 존재입니다.

하지만 그것은 은 포탄

나는 권장하지 않습니다 항상 고용에 명시적 인터페이스 구현.사람들은 두 가지 예는 곳들이 도움이 될 수 있습니다.

견적을 제프리 리히터에서 CLR 를 통해 C#
(에이미 수단 Explicit nterface Method mplementation)

그것은 매우 중요한 일부를 이해하는 결과 이 존재할 때 사용하여 EIMIs.고 있기 때문에 이러한 결과,당신이 시도해야 피 EIMIs 으로 많이 가능합니다.다행히,일반 인터페이스는 데 도움 당신이 피하기 EIMIs 습니다.하지만 거기에 될 수 있습야 하는 경우 그들을 사용하는(과 같은 두 가지 구현 인터페이스 방법과 동일한 이름 고 서명).여기에는 큰 문제 EIMIs:

  • 이 없는 방법을 설명하는 문서 유형별 를 구현하는 에이미는 방법,그리고 거기 은 Microsoft Visual Studio IntelliSense 을 지원합니다.
  • 값을 입력 인스턴스는 박스전할 때에는 인터페이스입니다.
  • 는 에이미 호출할 수 없으로 파생된 형식입니다.

를 사용하면 인터페이스 참고 모든 가상 체인할 수 있는 명시적으로 대체 에이미에서 파생된 클래스와 오브젝트와 같은 유형의 캐스팅을 인터페이스,가상 체인은 무시되고 명시적으로 구현이라고합니다.는 아무것도 하지만 다형성이다.

EIMIs 사용할 수도 있습을 숨기기 비 강력한 형식의 인터페이스 구성원에서 기본 프레임워크 인터페이스의 구현 등페<T> 그래서 당신의 클래스에 노출하지 않는다는 비 강력한 메서드를 직접하지만,정확한 구문.

외에 다른 이유는 이미 언급된 이 상황에서는 클래스를 구현하는 두 개의 서로 다른 인터페이스가 있는 시설/는 방법과 동일한 이름 및 서명이 있습니다.

/// <summary>
/// This is a Book
/// </summary>
interface IBook
{
    string Title { get; }
    string ISBN { get; }
}

/// <summary>
/// This is a Person
/// </summary>
interface IPerson
{
    string Title { get; }
    string Forename { get; }
    string Surname { get; }
}

/// <summary>
/// This is some freaky book-person.
/// </summary>
class Class1 : IBook, IPerson
{
    /// <summary>
    /// This method is shared by both Book and Person
    /// </summary>
    public string Title
    {
        get
        {
            string personTitle = "Mr";
            string bookTitle = "The Hitchhikers Guide to the Galaxy";

            // What do we do here?
            return null;
        }
    }

    #region IPerson Members

    public string Forename
    {
        get { return "Lee"; }
    }

    public string Surname
    {
        get { return "Oades"; }
    }

    #endregion

    #region IBook Members

    public string ISBN
    {
        get { return "1-904048-46-3"; }
    }

    #endregion
}

이 코드를 컴파일하고 확인을 실행하지만,제목 속성을 공유합니다.

분명히 우리가 원하는 값의 제목은 반환되는지 여부에 따라 달라 우리는 치료 Class1 책으로 또는 사람입니다.이 때 우리가 사용할 수 있는 명시적 인터페이스입니다.

string IBook.Title
{
    get
    {
        return "The Hitchhikers Guide to the Galaxy";
    }
}

string IPerson.Title
{
    get
    {
        return "Mr";
    }
}

public string Title
{
    get { return "Still shared"; }
}

알 수 있는 명시적 인터페이스를 정의는 유추하는 공공 그리고 그에 따른 선언할 수 없습을 공개한다(또는 그렇지 않으면)명시적으로 합니다.

참고 또한 당신은 여전히 수 있습니다"공유"버전(위와 같이),하지만 이것이 가능한 숙박 시설은 의심스럽습니다.아마도 그것으로 사용할 수 있습의 기본 구현은 제목 그래서는 기존의 코드를 수정할 수 없습 캐스팅 Class1IBook 또 IPerson.

를 정의하지 않은 경우에는"공유"(암시),제목,소비자의 Class1 명시적으로 캐스팅 인스턴스의 Class1IBook 또 IPerson 첫 번째 그렇지 않으면 코드를 컴파일되지 않습니다.

내가 사용하여 명시적 인터페이스를 구현하는 대부분의 시간입니다.여기에는 주된 이유입니다.

Refactoring 안전

을 변경할 때에는 인터페이스가 있다면 그것은 더 나은 컴파일을 확인할 수 있습니다.이것은 더 암시적으로 실현하였다.

두 가지 일반적인 케이스가 마음에 올:

  • 추가 기능을 인터페이스는 기존하는 클래스를 구현하는 이 인터페이스는 이미 일어나는 방법과 같은 서명으로 새로운 한.으로 이어질 수 있습을 예상치 못한 행동은 물리게 하는 몇 번입니다.그것은"어려운 경우"를 참조하십시오기 때문에 디버깅하는 기능을 가능성이 있지 않으로 다른 인터페이스 방법을 파일에서(자기 문서화 문제를 언급된 아래).

  • 을 제거하는 기능에서 인터페이스.암시적으로 구현 방법이 될 것입니다 갑자기 죽은 코드,하지만 명시적으로 구현되는 방법을 잡힐 것입하여 컴파일한 오류가 있습니다.는 경우에도 죽음 코드를 유지하고,원하는 것을 강요하고 그것을 검토하고 홍보한다.

그것은 불행한 것은 C#없는 키워드는 힘이 우리를 표시하는 방법으로는 암시적인 구현을 컴파일 할 수 있었습니다 추가 확인합니다.가상 방법 중 하나 없는 위의 문제로 인해 필요한 이용의 재정'과'새로운'.

참고:에 대한 수정 또는 드물게 변화하는 인터페이스(일반적으로 공급업체 API),이 문제가 되지 않습니다.내 자신의 인터페이스,하지만,나는 예측할 수 없는 경우/들이 어떻게 변화할 것입니다.

그것은 자기 문서화

면 나는'공공 bool Execute()'클래스에서,그것은 추가 작업 그는 그것의 일부 인터페이스입니다.누군가가 할 수있는 그것을 이렇게 말해서,또는 그것의 그룹에서 다른 인터페이스 구현,아래의 모든 지역 또는 그룹 의견 말하는"의 구현에서는 itask".물론,작동하는 경우에는 그룹 헤더가 없는 오프스크린..

반면:'bool 에서는 itask.Execute()'는 분명하고 명백하다.

분명 분리의 인터페이스 구현

내 생각으로 인해 인터페이스는 더 많은'공공'보다 공용 방법이기 때문에 만들어진출에 그냥 조금의 표면적의 콘크리트 형식입니다.그들이 감소형하는 기능이 동작 세트의 특성,등등.과 구현에,나는 그것을 유지하는 데 유용이 분리입니다.

로 내가 찾는 것을 통해 클래스의 코드,내가 올 때에 명시적 인터페이스 구현,내 두뇌동으로"코드는 계약"모드가 있습니다.종종 이러한 구현에서는 간단히 앞으로 다른 방법이지만,때로는 그들이 할 것이다 추가 주/param 확인,변환 들어오는 매개변수에 맞게 더 나은 내부 요건,또는 번역을 위한 버전 관리를 목적으로(즉여러 세대의 인터페이스는 모든 펀트 아래로 일반적인 구현에).

(나는 깨닫게는 대중 또한 코드를 계약이지만,인터페이스는 훨씬 더 강하고,특히 인터페이스 구동 codebase 어디에 직접 사용하여 콘크리트의 유형은 일반적으로 등록의 내부만 코드입니다.)

관련된: 이유는 2 위해 존.

게 장점이 이미 언급한 다른 답변에서 여기:

문제

그것은 모든 재미있고 행복.거기에 몇 가지 경우가 있습니다 나는 implicits:

  • 값 형식이기 때문에,필요한 것이 복싱과 낮은 perf.이것은 엄격한 규칙에 따라 인터페이스와 어떻게 그것이 의도된 사용할 수 있습니다.IComparable?암시적입니다.IFormattable?아마도 분명하게 명시되어 있습니다.
  • 사소한 시스템 인터페이스가 있는 방법을 자주라는 직접적으로(같은 IDisposable.폐기).

또한,그것은 고통이 될 수 있습을 하는 캐스팅을 할 때 실제로 구체적인 형식과 전화하려는 명시적 인터페이스 방법입니다.내가 다루는 이 두 가지 방법 중 하나:

  1. 추가 공중하고 인터페이스 방법을 기대하여 그들을 위해 구현됩니다.일반적으로 발생하는 간단한 인터페이스를 작업할 경우 내부적으로 합니다.
  2. (나이 선호하는 방법)추가 public IMyInterface I { get { return this; } } (는 인라인되)및 전화 foo.I.InterfaceMethod().여러 개 있는 경우에는 인터페이스에 필요한 이 능력을 확장합 이름을 넘어서(내가 그것을 경험의 희귀는 내가 이해 필요).

를 구현하는 경우 명시적으로,당신이 할 수있을 것입니다 참조 인터페이스 구성원을 통해 참고하는 형식의 인터페이스입니다.에 대한 참조는 유형의 구현하는 클래스에 노출되지 않습니다 그 인터페이스 구성원.

는 경우 구현하는 클래스가 공개되지 않을 제외한 방법을 만드는 데 사용되는 클래스(수 있는 공장 또는 IoC 컨테이너)및를 제외한 인터페이스에 대한 방법(물론),다음은 보이지 않는데 이점을 명시적으로 구현하는 인터페이스가 있습니다.

그렇지 않으면 명시적으로 인터페이스를 구현하는지 확인 참조를 당신의 콘크리트 구현하는 클래스를 사용하지 않을 변경할 수 있는 구현이 나중에 시간이다."확인",제가 생각은"이용".잘 고려한 구현하여 이 작업을 수행할 수 있습 없이 명시적인 구현합니다.

단점,제 생각에는 자신을 발견 할 것이 형식 사이의 캐스팅/인터페이스에서 구현하는 코드가 있는 비공개 회원입니다.

다음과 같은 많은 것을 장점은 단점이(그리고 반대로).명시적으로 인터페이스를 구현하는 것을 보장 콘크리트 클래스를 구현하는 코드가 노출되지 않습니다.

암시적 인터페이스는 구현이 어디 있는 방법으로 동명의 인터페이스입니다.

명시적 인터페이스 구현은 당신이 명시적으로 선언하는 인터페이스 방법에 속한다.

interface I1
{
    void implicitExample();
}

interface I2
{
    void explicitExample();
}


class C : I1, I2
{
    void implicitExample()
    {
        Console.WriteLine("I1.implicitExample()");
    }


    void I2.explicitExample()
    {
        Console.WriteLine("I2.explicitExample()");
    }
}

MSDN: 암시적이고 명시적 인터페이스 구현

모든 클래스 구성원 인터페이스를 구현하는 수출 선언하는 의미와 유사한 방법으로 VB.NET 인터페이스 선언을 작성,예를 들어,

Public Overridable Function Foo() As Integer Implements IFoo.Foo

이름 클래스의 구성원이 자주는 인터페이스의 회원,그리고 클래스 구성원 자주됩니다 공용도 그 것이 필요합니다.수도를 선언:

Protected Overridable Function IFoo_Foo() As Integer Implements IFoo.Foo

이 경우 클래스와 그 유도체할 수 있도록 허락해 주실 것 액세스 클래스 구성원을 사용하여 이름 IFoo_Foo, 지만,외부 세계에만 액세스할 수 있는 특정 회원으로 캐스팅 IFoo.이러한 접근은 종종 좋은 경우에는 인터페이스 방법 있을 것이다 지정 동작에 구현하지만, 동작에만 일부는[예:지정된 동작에 대한 읽기 전용의 컬렉션 IList<T>.Add 방법은 던져 NotSupportedException].불행하게도,다만 적절한 방법으로 구현하는 인터페이스에서는 C#:

int IFoo.Foo() { return IFoo_Foo(); }
protected virtual int IFoo_Foo() { ... real code goes here ... }

으로하지 않습니다.

하나의 중요한 사용은 명시적 인터페이스 구현은 때에는 인터페이스를 구현할 필요가와 혼합된 가시성.

문제고 솔루션은 설명한 문서 C#내부 인터페이스.

예를 들어,을 보호하려는 경우 누설의 개체를 사용 층,이 기술을 지정할 수 있습니다 다른 가시성 구성원의 일으킬 수 있는 누설입니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top