인터페이스를 명시 적 또는 암시 적으로 구현하는 것의 차이점은 무엇입니까?


64

Visual Studio에서 인터페이스를 마우스 오른쪽 단추로 클릭하고 인터페이스 구현 또는 명시 적으로 인터페이스 구현을 선택할 수 있습니다.

Visual Studio 스크린 샷

public class Test : ITest
{
    public string Id // Generated by Implement Interface
    {
        get { throw new NotImplementedException(); }
    }

    string ITest.Id // Generated by Implement Interface Explicitly
    {
        get { throw new NotImplementedException(); }
    }
}

둘 사이의 유일한 차이점은 인터페이스 명시 적 구현을 ​​선택하면 인터페이스 이름이 인터페이스 속성 및 메소드가 작성 될 때 인터페이스 특성 및 메소드에 추가된다는 것입니다.

메소드 / 프로퍼티의 출처를 알 수 있기 때문에 코드를 조금 더 읽기 쉽게 만듭니다. 그러나 클래스 사용 또는 컴파일 방식에 어떤 차이가 있습니까? 내 인터페이스를 암시 적으로 또는 명시 적으로 구현하면 정말 중요합니까?

답변:


51

SO의 "암시 적 vs 명시 적 인터페이스 구현"에 대한 Andrew Barrett의 최상위 답변을 확인하십시오 .

원래:

  • 암시 적 : 인터페이스 메서드 및 속성이 마치 클래스의 일부인 것처럼 액세스합니다.
  • 명시 적 : 클래스를 구현 된 인터페이스로 취급 할 때 메소드 및 특성에만 액세스 할 수 있습니다.

코드 예 :

함축 [암시]적인, 내재하는:

Test t = new Test();
t.Id; // OK
((ITest)t).Id; // OK

명백한,있는 그대로의:

Test t = new Test();
t.Id; // Not OK
((ITest)t).Id; // OK

"언제"라는 관점에서 인터페이스를 명시 적으로 구현해야하는 경우, 클래스에 이미 인터페이스의 메소드 중 하나와 동일한 서명을 가진 메소드가 있거나 클래스가 동일한 서명을 가진 메소드를 공유하는 여러 인터페이스를 구현하는 경우 호환되지 않는 계약.


1
또한 안전하지 않은 작업으로 일종의 "숨겨진"인터페이스를 갖는 데 유용한 명시 적 구현이 발견되었습니다. 또한 이러한 메소드에 대한 호출이 더 두드러져 안전하지 않은 것들에 좋은 것입니다.
Tamás Szelei

또한 속성 / 메소드를 참조 할 때마다 개체를 박스 / 언 박스 해제해야하므로 명시 적 인터페이스를 사용하면 성능 비용이 발생한다는 점도 언급 할 가치가 있습니다. 이 때문에 가능하면 암시 적 인터페이스를 사용하는 것이 좋습니다
Rachel

3
@Rachel : 성능 비용은 가치 유형에만 적용된다는 것을 알고 있습니다.
Groky

8

메소드를 호출하는 방법에도 차이가 있습니다.

사용하는 경우 명시 적 인터페이스 구현을, 당신은 특정 구현을 호출하기 위해 인터페이스 유형을 사용해야합니다.

따라서 코드를 호출 할 ITest때에 액세스하려면 유형의 변수를 사용해야합니다 ITest.Id.

MSDN의 Explicit Interface Implementation (C # 프로그래밍 가이드) 기사 에 좋은 예가 있습니다.


4

동일한 메소드를 정의하는 두 개의 인터페이스를 구현할 수 있습니다. 그러나 인터페이스를 명시 적으로 구현하면 해당 명시 적 인터페이스에 변수를 입력 한 경우에만 메소드에 액세스 할 수 있습니다.

참조 : 명시 적 인터페이스 구현 학습서


4

편집 : 차이 가 없어야 합니다. 클래스가 동일한 속성을 가진 두 개의 인터페이스를 구현하지 않으면 멤버를 액세스하기 전에 관련 인터페이스로 캐스팅 해야하기 때문에 그렇게해서는 안됩니다 .

public interface ITest
{
    string Id { get; }
}

public interface IAlsoTest
{
    string Id { get; }
}

public interface ITestToo
{
    int Id { get; }
}

public class Test : ITest, IAlsoTest
{
    // Valid implicit implementation of BOTH interfaces
    public string Id
    {
        get { throw new NotImplementedException(); }
    }
}

public class TestSeparately : ITest, ITestToo
{
    // This way we can do different things depending
    // on which interface the callee called from.
    string ITest.Id
    {
        get { throw new NotImplementedException(); }
    }

    int ITestToo.Id
    {
        get { throw new NotImplementedException(); }
    }
}

public class TestOuch
{
    public void DoStuff()
    {
        var ts = new TestSeparately();

        // Works
        Console.WriteLine(((ITest)ts).Id);

        // Works
        Console.WriteLine(((ITestToo)ts).Id);

        // Not valid! Which one did we want to call?
        Console.WriteLine(ts.Id);
    }
}

하나의 인터페이스 (항상 잊어 버리는 : S) 만 사용하더라도 인터페이스 멤버를 명시 적으로 구현하면 예제 사용법이 유지되므로 가능한 한 클래스 멤버를 숨기므로 가능한 한 명시 적으로 구현하지 마십시오. 올바른 인터페이스로 캐스팅하지 마십시오 (혼란 스럽습니다).


3

Jalayan의 답변을 바탕으로

  • 암시 적 : 인터페이스 메서드 및 속성이 마치 클래스의 일부인 것처럼 액세스합니다.
  • 명시 적 : 클래스를 구현 된 인터페이스로 취급 할 때 메소드 및 특성에만 액세스 할 수 있습니다.

여기에 이미지 설명을 입력하십시오

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.