2010-04-02 6 views
55

C# 4.0 사용 - 인터페이스 및 인터페이스를 구현하는 클래스 작성. 인터페이스에 선택적 매개 변수를 선언하고 클래스에 반영하도록하고 싶습니다. 그래서, 다음과 같습니다 :인터페이스에 대한 선택적 매개 변수

public interface IFoo 
{ 
     void Bar(int i, int j=0); 
} 

public class Foo 
{ 
     void Bar(int i, int j=0) { // do stuff } 
} 

이 컴파일,하지만 제대로 보이지 않습니다. 인터페이스는 선택적 매개 변수를 가져야합니다. 그렇지 않으면 인터페이스 메소드 서명에 올바르게 반영되지 않기 때문입니다.

선택적 매개 변수를 건너 뛰고 Null 허용 유형 만 사용해야합니까? 아니면 부작용이나 결과없이 의도대로 작동합니까?

+2

아래의 Martin의 의견은 다양한 함정에 대한 자세한 예제를 제공하며 컴파일러가 일치하지 않는 기본 인수를 플래그로 표시하기를 바랍니다. 즉, 다른 개발자가 볼 수있는 인터페이스와 구현 수준 모두에서 개발자로서의 의도를 나타 내기 때문에이 코드를 내 코드에서 사용하고 있습니다. –

+0

흥미로운 관련 질문 인 "[인터페이스에서 선택적 매개 변수를 선언 할 이유가 있습니까?] (https : // stackoverflow."[클래스를 구현할 때 인터페이스에 적용되지 않는 C# 4 선택적 매개 변수는 왜 정의되어 있습니까?] (https://stackoverflow.com/questions/4922714/)", 두 번째로 흥미로운 [Lippert의 대답] (https://stackoverflow.com/a/4923642/1028230) – ruffin

답변

28

당신은 사전 선택 - 매개 변수의 대안을 고려할 수 :

public interface IFoo 
{ 
    void Bar(int i, int j); 
} 

public static class FooOptionalExtensions 
{ 
    public static void Bar(this IFoo foo, int i) 
    { 
     foo.Bar(i, 0); 
    } 
} 

새로운 언어 기능의 모양이 마음에 들지 않으면, 당신은 그것을 사용할 필요가 없습니다.

+40

... 새롭고 빛나는! :-) – bryanjonker

+1

어떻게 작동하는지에 대한 추가 설명을 제공하거나 "pre-optional-paremeters alternative"라고하는 것에 대한 링크. 미래의 사용자를 도울 수 있습니다! : –

+0

물론 (이전 C# 3 확장 메소드를 도입 한)이 방법은 두 가지 모두에서 메소드 오버로딩을 사용하는 것이 었습니다 클래스 및 인터페이스에 액세스 할 수 있습니다. 클래스 오버로드에 대한 액세스 권한이있는 경우 코드를 한 곳에서 유지하므로 확장 메서드보다 오버로드가 더 좋습니다. –

1

외모로 살펴보면 성취하고자하는 바를 정확히 수행합니다.

+2

이 질문에 대한 답변을 제공하지 않습니다. 작성자의 설명을 요청하거나 설명을 요청하려면 , 남겨두고 게시물 아래에 NT. –

+3

잘 모르겠습니다. 그것은 저에게 질문하는 질문에 대한 직접적인 대답 인 것 같습니다 : "또는 부작용이나 결과없이 의도대로 작동합니까?" – MojoFilter

3

어때?

+0

@Iznogood - 여기에서 승인 한 편집은 분명히 유효한 편집이 아닙니다. http://stackoverflow.com/review/suggested-edits/1041521. 수정 사항을 검토 할 때 좀 더주의하십시오. – LittleBobbyTables

44

실제로 이상한 점은 인터페이스의 선택적 매개 변수에 입력 한 값이 실제로 달라진다는 것입니다. 값이 인터페이스 세부 사항인지 구현 세부 사항인지 여부를 질문해야한다고 생각합니다. 나는 후자를 말했을 것이지만 물건은 전처럼 행동한다. 다음 코드는 예를 들어 1 0 2 5 3 7을 출력합니다.

실수 것 같다 무엇
// Optput: 
// 2 5 
namespace ScrapCSConsole 
{ 
    using System; 

    interface IMyTest 
    { 
     void MyTestMethod(int notOptional, int optional = 5); 
    } 

    class MyTest : IMyTest 
    { 
     public void MyTestMethod(int notOptional, int optional) 
     { 
      Console.WriteLine(string.Format("{0} {1}", notOptional, optional)); 
     } 
    } 

    class Program 
    { 
     static void Main(string[] args) 
     { 
      MyTest myTest1 = new MyTest(); 
      // The following line won't compile as it does not pass a required 
      // parameter. 
      //myTest1.MyTestMethod(1); 

      IMyTest myTest2 = myTest1; 
      myTest2.MyTestMethod(2); 
     } 
    } 
} 

그러나 경우이다 : 재미의 종류 무엇

// Output: 
// 1 0 
// 2 5 
// 3 7 
namespace ScrapCSConsole 
{ 
    using System; 

    interface IMyTest 
    { 
     void MyTestMethod(int notOptional, int optional = 5); 
    } 

    interface IMyOtherTest 
    { 
     void MyTestMethod(int notOptional, int optional = 7); 
    } 

    class MyTest : IMyTest, IMyOtherTest 
    { 
     public void MyTestMethod(int notOptional, int optional = 0) 
     { 
      Console.WriteLine(string.Format("{0} {1}", notOptional, optional)); 
     } 
    } 

    class Program 
    { 
     static void Main(string[] args) 
     { 
      MyTest myTest1 = new MyTest(); 
      myTest1.MyTestMethod(1); 

      IMyTest myTest2 = myTest1; 
      myTest2.MyTestMethod(2); 

      IMyOtherTest myTest3 = myTest1; 
      myTest3.MyTestMethod(3); 
     } 
    } 
} 

는 인터페이스를 구현하는 매개 변수 옵션 클래스를 만드는 경우는 동일한 작업을 수행 할 필요가 없다는 것입니다 인터페이스를 명시 적으로 구현하면 클래스에서 옵션 값에 대해 제공하는 값이 무의미합니다. 다음 예제에서 값 9를 어떻게 사용할 수 있습니까? 이것은 컴파일 할 때 경고조차하지 않습니다.

// Optput: 
// 2 5 
namespace ScrapCSConsole 
{ 
    using System; 

    interface IMyTest 
    { 
     void MyTestMethod(int notOptional, int optional = 5); 
    } 

    class MyTest : IMyTest 
    { 
     void IMyTest.MyTestMethod(int notOptional, int optional = 9) 
     { 
      Console.WriteLine(string.Format("{0} {1}", notOptional, optional)); 
     } 
    } 

    class Program 
    { 
     static void Main(string[] args) 
     { 
      MyTest myTest1 = new MyTest(); 
      // The following line won't compile as MyTest method is not available 
      // without first casting to IMyTest 
      //myTest1.MyTestMethod(1); 

      IMyTest myTest2 = new MyTest();    
      myTest2.MyTestMethod(2); 
     } 
    } 
} 
2

구현시 매개 변수를 선택적으로 지정할 필요는 없습니다. 그러면 코드가 다소 의미가 있습니다.

public interface IFoo 
{ 
     void Bar(int i, int j = 0); 
} 

public class Foo 
{ 
     void Bar(int i, int j) { // do stuff } 
} 

이렇게하면 기본값이 명확합니다. 사실, 인터페이스가 기본값을 제공하기 때문에 구현의 기본값이 아무런 영향을 미치지 않을 것이라고 확신합니다.

+2

참조가 인터페이스가 아닌 클래스로 입력 된 경우 구현의 기본값이 적용됩니다. –

2

고려해야 할 사항은 인터페이스의 반영을 기반으로 작동하는 조롱 프레임 워크가 사용될 때 일어나는 일입니다. 선택적 매개 변수가 인터페이스에 정의 된 경우 인터페이스에 선언 된 내용을 기반으로 기본값이 전달됩니다. 하나의 문제는 정의에 대해 다른 선택적 값을 설정하는 것을 막을 수 없다는 것입니다.

관련 문제