인터페이스에 정의 된 C # 4 선택적 매개 변수가 클래스 구현시 적용되지 않는 이유는 무엇입니까?


361

당신은 당신이 인터페이스에서 선택적 매개 변수를 지정하면 나는 C # 4의 선택적 매개 변수와 그 눈치 t는, 돈 어떤 구현 클래스의 해당 매개 변수의 선택을해야합니다 :

public interface MyInterface
{
    void TestMethod(bool flag = false);
}

public class MyClass : MyInterface
{
    public void TestMethod(bool flag)
    {
        Console.WriteLine(flag);
    }
}

따라서:

var obj = new MyClass();        
obj.TestMethod(); // compiler error

var obj2 = new MyClass() as MyInterface;
obj2.TestMethod(); // prints false

선택적 매개 변수가 이런 식으로 작동하도록 설계된 이유를 아는 사람이 있습니까?

한편으로는 인터페이스에 지정된 기본값을 재정의하는 기능이 정직하지만 유용하지만 인터페이스에 기본값을 지정할 수 있는지 여부는 확실하지 않지만 구현 결정이 필요하다고 생각합니다.

반면에,이 연결 해제는 구체적 클래스와 인터페이스를 항상 호환 적으로 사용할 수있는 것은 아닙니다. 물론 구현에 기본값이 지정된 경우 문제가되지 않지만 구체적인 클래스를 인터페이스로 노출하는 경우 (예를 들어 일부 IOC 프레임 워크를 사용하여 콘크리트 클래스를 주입하는 경우) 실제로는 없습니다. 호출자가 항상 기본값을 제공해야합니다.


22
그들은 선택 적이기 때문에?
오디드

1
그러나 객체 인스턴스를 캐스트 MyInterface하고 선택적 매개 변수를 사용하여 호출 할 수 있습니다 ((MyInterface)obj).TestMethod();.
Jim Mischel

7
@oded-계약서에서이 매개 변수가 선택 사항이라고 말하면 구현자가이를 선택적으로 만들 수없는 이유는 무엇입니까? 계약을 사용하려는 사람에게 혼란을 초래하지 않습니까?
theburningmonk

1
이 경우 구현 메소드를 호출하지 않고 구현에서 매개 변수가 선택적이라고 말할 수 있습니다. 클래스에서 메소드를 호출 할 때 클래스 규칙을 따라야합니다 (매개 변수는 클래스에서 선택적이 아니므로 클래스에서 '없는 경우 메서드를 호출하지 마십시오.'두 번째로 인터페이스를 구현할 때는 인터페이스 규칙을 따라야하므로 선택적 매개 변수가 있거나없는 메서드를 재정의 할 수 있습니다. 그냥 의견.
Mohamad Alhamoud

답변:


235

업데이트 : 이 질문은 2011 년 5 월 12 일에 제 블로그의 주제였습니다. 훌륭한 질문에 감사드립니다!

설명하는 인터페이스와이를 구현하는 백개의 클래스가 있다고 가정하십시오. 그런 다음 인터페이스 메소드 중 하나의 매개 변수 중 하나를 선택적으로 작성하기로합니다. 컴파일러가 개발자가 해당 인터페이스 메소드의 모든 구현을 찾아서 매개 변수를 선택 사항으로 만들도록 강요하는 것이 옳은 일이라고 제안하고 있습니까?

우리가 그렇게했다고 가정 해보십시오. 이제 개발자에게 구현을위한 소스 코드가없는 것으로 가정하십시오.


// in metadata:
public class B 
{ 
    public void TestMethod(bool b) {}
}

// in source code
interface MyInterface 
{ 
    void TestMethod(bool b = false); 
}
class D : B, MyInterface {}
// Legal because D's base class has a public method 
// that implements the interface method

D의 저자는 이것을 어떻게해야합니까? 그들은 세계에서 전화로 B의 작성자를 불러서 메소드에 선택적 매개 변수를 갖도록 B의 새로운 버전을 보내달라고 요청합니까?

그것은 날지 않을 것입니다. 어떤 경우 2 개의 사람들은 B의 저자 호출, 그 중 하나는 기본 사실이되고 싶어 그 중 하나는 거짓되고 싶어? B의 저자가 단순히 게임을 거부하면 어떻게 될까요?

아마도이 경우에는 다음과 같이 말해야합니다.

class D : B, MyInterface 
{
    public new void TestMethod(bool b = false)
    {
        base.TestMethod(b);
    }
}

제안 된 기능은 대표 력의 상응하는 증가없이 프로그래머에게 많은 불편 함을 추가하는 것으로 보인다. 사용자에게 증가 된 비용을 정당화하는이 기능의 강력한 이점은 무엇입니까?


업데이트 : 아래 의견에서 supercat은 언어에 진정한 힘을 더하고이 질문에 설명 된 것과 유사한 시나리오를 가능하게하는 언어 기능을 제안합니다. 참고로,이 기능 (인터페이스의 기본 메소드 구현)은 C # 8에 추가됩니다.


9
@ supercat : 우리는 그렇게 할 계획이 없지만 그런 기능이 가능합니다. 이전에 제안되었습니다. C # 4의 디자인 프로세스 중에 우리는 "확장 기능"기능이라고하는 많은 기능을 살펴 보았습니다. 확장 방법이 있으므로 확장 이벤트, 확장 속성, 확장 생성자, 확장 인터페이스 등이 있다는 의미입니다. . 인터페이스에 "연결"하고 "이 메소드는이 인터페이스의 기본 구현"이라고 말할 수있는 클래스는 "확장 인터페이스"를 특성화하는 한 가지 방법입니다. 흥미로운 생각입니다.
Eric Lippert

16
내가 직관적이지 않다고 생각하는 이유에 대한 나의 추론을 명확히하기 위해 : 선택적 매개 변수는 "메소드의 구현 자에게 선택적"이 아니라 "메소드의 호출자에게 선택적"이다.
Stefan de Kok

8
"그들은 당신의 세계에서 전화로 B의 저자를 불러서 그들에게 새로운 버전 [...]을 보내달라고 요청해야합니까?" 아니요, 전화가 필요하지 않습니다. B는 더 이상 MyInterface의 함정으로 간주 될 수 없어야하며 D 작성자는 컴파일러가이를 인식 할 수 있습니다. D의 작성자는 인터페이스 작성자가 요구하는 기본 매개 변수를 허용하는 TestMethod를 사용하여 D를 구현해야합니다. 누군가 인터페이스 작성자가 제한을 적용하기를 원하기 때문에 인터페이스 작성자가 제한 조건을 적용하지 못하도록하는 것입니다. 좋은 주장이 아닙니다.
Philofinfinitejest

7
@EricLippert 코딩 편의를 위해 선택적 파라미터가 지정되는 경우 구현에 불편을주는 것은 반 직관적입니다. 그러나 선택적 매개 변수를 사용하여 강력한 기능 인 메서드 과부하를 최소화하는 경우 이러한 선택적 값은 큰 의미를 가질 수 있으며 무시하면 그 힘을 확실히 희석시킵니다. 구체적인 구현이 인터페이스와 다른 기본값을 지정하는 경우는 말할 것도 없습니다. 허용하기에는 매우 이상한 분리처럼 보입니다.
philofinfinitejest

8
나는 @philofinfinitejest에 동의합니다. 인터페이스는 무엇을 할 수 있는지 알려줍니다. 인터페이스가 지정한 것과 다른 기본값으로 인터페이스의 구현이 전달되면 어떻게 알 수 있습니까? 이봐, 나는 기본값으로 true를 전달하는 인터페이스를 가지고 있는데, 왜 이것이 거짓이됩니까? 예상 한 인터페이스를 얻지 못한 것 같습니다. 더 나쁜 것은 이제 인터페이스가 아닌 구현에 프로그래밍해야합니다.
aaronburro

47

선택적 매개 변수에는 속성이 태그로 지정되어 있습니다. 이 속성은 컴파일러에게 호출 매개 변수에 해당 매개 변수의 기본값을 삽입하도록 지시합니다.

C # 코드가 JIT 시간이 아닌 IL로 컴파일 될 때 호출 obj2.TestMethod();이 대체됩니다 obj2.TestMethod(false);.

따라서 항상 호출자가 선택적 매개 변수와 함께 기본값을 제공합니다. 또한 이진 버전 관리에 영향을줍니다. 기본값을 변경했지만 호출 코드를 다시 컴파일하지 않으면 이전 기본값이 계속 사용됩니다.

반면에,이 연결 해제는 구체적 클래스와 인터페이스를 항상 호환 적으로 사용할 수있는 것은 아닙니다.

인터페이스 메소드가 명시 적 으로 구현 된 경우 이미 그렇게 할 수 없습니다 .


1
구현자가 강제로 명시 적으로 구현하도록 할 수 있습니까?
호감

30

기본 매개 변수는 런타임이 아닌 컴파일 타임에 해결되기 때문입니다. 따라서 기본값은 호출되는 오브젝트가 아니라 호출되는 참조 유형에 속합니다.


7

선택적 매개 변수는 내가 이해 한 매크로 대체와 같습니다. 메소드의 관점에서 실제로 선택 사항은 아닙니다. 그 결과는 인터페이스로 캐스트 할 때 다른 결과를 얻는 위치에 나타나는 동작입니다.

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