2009-07-24 3 views
8

선택적 구현 방법으로 인터페이스를 정의 할 수 있습니까? 예를 들어 내 핵심 라이브러리 IDataReader에 따라 다음 인터페이스 정의를 가지고 :인터페이스에서 선택적 구현 방법을 정의 하시겠습니까?

public interface IDataReader<T> { 
    void StartRead(T data); 
    void Stop(); 
} 

하지만, 내 현재의 구현에, 정지() 메소드를 사용하거나 구현 된 적이있다. 내 모든 구현 클래스,이 방법은 기본적으로 던져 NotImplementedExcetion()로 구현 될 필요가 있습니다 :

물론
class MyDataReader : IDataReader<MyData> { 
    ... 
    public void Stop() 
    { 
    // this none implementaion looks like uncompleted codes 
    throw NotImplementedException(); 
    } 

, 내가 던져 예외 코드를 제거 할 수 있습니다 빈 둡니다.

이 데이터 판독기 인터페이스를 설계 할 때 독서 프로세스를 중지하는 방법을 제공해야한다고 생각했습니다. 어쩌면 우리는 앞으로 언젠가 Stop()을 사용할 것입니다.

어쨌든 선택적 구현 방법으로이 Stop() 메소드를 만들 수 있는지 확실하지 않습니까? 내가 생각할 수있는 유일한 방법은 중지와 IDataReader 및 IDataReader2 같은 다른 인터페이스를 정의하는 것입니다. 또 다른 옵션은 다음과 같이 인터페이스에이 일을 휴식하는 것입니다

reader.StartRead(myData); 
.... 
// some where when I need to stop reader 
IStop stoppable = reader as IStop; 
if (stoppable != null) stoppable.Stop(); 
... 
: 내 구현의 경우

interface IDataReader<T> { 
    void StartRead(T data); 
} 

interface IStop { 
    void Stop(); 
} 

, 나는 캐스트 또는 내 구현() 메소드 중지를 지원하는지 확인하려면 IStop로 사용해야합니다

아직도 그 코드를 써야합니다. 어떤 제안? .Net 또는 C#의 인터페이스에서 선택적 구현 메소드를 정의 할 수있는 방법이 있는지 확실하지 않은가요?

답변

6

는 BCL에서 흔하다 다른 접근법 (IBindingList, 예를 들어, 이것의 예), 즉

bool SupportsStop {get;} 
void Stop(); 

동일한 인터페이스 Supports*이다.

나는 그것이 "순수한"또는 아무것도 인 척 아니지만, 작동 -하지만 당신이 지금 하나, 기능별로하지 구현하는 방법을 의미합니다. 별도의 인터페이스 (예 : IStoppableReader)가 적합 할 수 있습니다.

구현시 구현 사이에 공통적 인 정보가있는 경우 확장 메소드를 사용할 수 있습니다. 간단한 예를 들면 다음과 같습니다.

public static void AddRange<T>(this IList<T> list, IEnumerable<T> items) { 
    foreach(T item in items) list.Add(item); 
} 

(또는 이에 상응하는 인터페이스).당신이 구체적인 유형에 대한보다 전문적인 버전을 제공하는 경우, 그것은 우선합니다 (그러나 호출자가 변수 등의 구체적인 유형이 아닌 인터페이스에 대해 알고있는 경우에만). 고의로 List<T>을 사용하여 위, 사람이 여전히 AddRangeList<T>의 버전을 사용와 그래서; 그러나 만약에 List<T>이 있고 그것을 단지 IList<T>으로 알고 있다면, 그것은 확장 메소드를 사용할 것입니다.

4

코드에서 어떤 클래스가 실제로 Stop() 구현하지 않으며, 당신은 당신이 당신의 인터페이스에 필요하지 않은 미래에 그렇게 할 명확한 계획을하지 않은 경우. 그렇지 않으면 일부이 아니라 개체의 모든이 "고정 가능"인 경우 실제로 올바른 방법은 IStoppable과 같은 별도의 인터페이스로 만들고 클라이언트는 필요에 따라이를 쿼리해야합니다.

0

구현에서 인터페이스 메소드 Stop을 구현하지 않으면 인터페이스와 함께 제공되는 계약이 분명히 중단됩니다. Exception을 적절히 구현하거나 예외를 던지지 않고 비워 두거나 인터페이스를 다시 설계해야합니다 (계약을 변경하기 위해).

최고 감사합니다.

7

흥미 롭습니다. 여기 당신을 인용 할 것이다 :

하지만, 내 현재 구현에, 정지() 메소드를 사용하거나 구현 된 적이 . 모든 내 구현 클래스에서,이 이 방법은 기본적으로 던져 NotImplementedExcetion()로 구현 될 :

  1. 중지를 제거 :이 경우

, 당신은 두 가지 옵션이 있습니다() 메소드를 호출한다.인터페이스가 구현자인 경우 은 분명히 여기에 속하지 않습니다..

  • 인터페이스 대신 추상 기본 클래스로 인터페이스를 변환하십시오. 이렇게하면 필요할 때까지 빈 Stop() 메서드를 재정의 할 필요가 없습니다.

업데이트 내가 방법을 선택 할 수 있다고 생각하는 유일한 방법은 방법은 이전에 null의 경우 다음 평가 (메소드의 서명과 유사한 대리자 형식의) 변수에 방법을 지정하는 것입니다 어디서나 전화하려고합니다.

이것은 일반적으로 이벤트 처리기에 대해 수행되며 핸들러는 존재할 수도 있고 없을 수도 있으며 선택 사항으로 간주 될 수 있습니다.

+0

나는 귀하의 요지를 보았습니다. 나는 실제로 그 방법을 제거했다. 이것은 내 통제하에있다. 그러나, 나는 그것을 한 후에, .Net에서 메서드 옵션을 만들 수있는 방법이 있는지 알아 내려고 노력했다. 인터페이스를 통해 프로세스를 중단해야하는 경우에 대비하여 선택적으로 유지하고 싶습니다. –

+0

답변 : 옵션 방법을 업데이트 할 예정입니다. –

4

메서드가 구현에 적합하지 않은 경우 Reset을 호출 할 때 대부분의 반복기에서와 마찬가지로 InvalidOperationException을 던져 넣으십시오. 대안은 System.IO에 의해 사용되는 경향이있는 NotSupportedException입니다. 후자는 더 논리적입니다 (객체의 현재 상태, 구체적 유형과는 아무런 관련이 없기 때문에).하지만 전자는 내 경험에서 더 일반적으로 사용됩니다.

그러나 실제로 필요할 때만 인터페이스에 넣는 것이 좋습니다. 아직 Stop을 제거 할 수있는 위치에 있다면 나는 너 였으면 그렇게 할 것입니다.

언어 또는 CLR의 선택적 인터페이스 구성원에 대한 통합 지원은 없습니다.

+3

.NET에 System.NotSupportedException이 있습니다.) –

+0

가 동의합니다. C#에서는 선택적 구현이 지원되지 않는 것처럼 보입니다. 사용하지 않는 메소드와 함께 .Net 핵심 인터페이스를 구현해야하는 경우가 많습니다. –

+0

@Oliver : 맞습니다. 두 가지를 모두 가지고있는 것은 엉망입니다. 나는 대답을 편집 할 것입니다. –

0

C# 버전 4 (or vNext)는 default implementation for interfaces을 고려하고 있습니다. - 나는 그걸 몇 달 전에 channel9에 들었습니다.).

기본 구현을 사용하는 인터페이스는 추상 기본 클래스처럼 약간 동작합니다. 이제는 여러 인터페이스를 상속받을 수 있습니다. 이는 C#이 기본 구현을 사용하는 인터페이스의 형태로 다중 상속을 가져올 수 있음을 의미합니다.

그때까지 당신은 ... 멀리 확장 방법과

를 얻을 수 있습니다 또는 당신의 유형은 대의원의 사용을 만들 수 있습니다. 정보에

interface IOptionalStop 
{ 
    Action Stop { get; } 
} 

public class WithStop : IOptionalStop 
{ 
    #region IOptionalStop Members 

    public Action Stop 
    { 
     get; 
     private set; 
    } 

    #endregion 

    public WithStop() 
    { 
     this.Stop = 
      delegate 
      { 
       // we are going to stop, honest! 
      }; 
    } 
} 

public class WithoutStop : IOptionalStop 
{ 
    #region IOptionalStop Members 

    public Action Stop 
    { 
     get; 
     private set; 
    } 

    #endregion 
} 


public class Program 
{ 
    public static string Text { get; set; } 


    public static void Main(string[] args) 
    { 
     var a = new WithStop(); 

     a.Stop(); 

     var o = new WithoutStop(); 

     // Stop is null and we cannot actually call it 
     a.Stop(); 

    } 
} 
+1

C# 4.0에는 "인터페이스의 기본 구현"이 없습니다. –

+0

너무 슬퍼합니다. 나는 이것을하기가 아주 쉬워야한다고 생각한다. 새로운 키 지시문을 추가하십시오. 메소드 앞에 옵션 .net 컴파일러가이 메소드에 대해 빈 본문 코드를 생성합니다. 구현되어 있지 않은 경우는 아무것도 실시하지 않고 예외는 없다면이 선택적 메소드를 호출하십시오. 물론 이것은 사람들이 너무 많은 나쁜 인터페이스를 던질 수있는 문을 열 수 있습니다. 옵션으로 구현할 가치가 있지만 남용 될 수 있습니다. 그냥 내 코멘트. –

+0

몇 가지 오타가 있습니다. 그 죄송합니다. 지금 캐나다에서는 너무 늦었습니다. –

관련 문제