선택적 매개 변수 또는 오버로드 된 생성자


28

나는 DelegateCommand을 구현하고 있으며 생성자를 구현하려고 할 때 다음 두 가지 디자인 선택을 생각해 냈습니다.

1 : 여러 개의 오버로드 된 생성자

public DelegateCommand(Action<T> execute) : this(execute, null) { }

public DelegateCommand(Action<T> execute, Func<T, bool> canExecute)
{
    this.execute = execute;
    this.canExecute = canExecute;
}

2 : 선택적 매개 변수를 가진 생성자가 하나만 있음

public DelegateCommand(Action<T> execute, Func<T, bool> canExecute = null)
{
    this.execute = execute;
    this.canExecute = canExecute;
}

제안 된 두 가지 방법 중 하나가 어떤 장점과 단점을 가지고 있는지 알지 못하기 때문에 어느 것을 사용 해야할지 모르겠습니다 . 둘 다 다음과 같이 호출 할 수 있습니다.

var command = new DelegateCommand(this.myExecute);
var command2 = new DelegateCommand(this.myExecute, this.myCanExecute);

누군가 올바른 방향으로 나를 가리키고 피드백을 줄 수 있습니까?


4
키스와 야니. 의심스러운 경우 두 가지를 모두 구현하십시오. 잠시 후 두 생성자 모두에 대한 참조를 검색하십시오. 그들 중 하나가 외부에서 소비되지 않았다면 놀라지 않을 것입니다. 또는 조금 소비되었습니다. 이것은 코드의 정적 분석 수행을 쉽게 찾을 수있는 것입니다.
Laiv

1
정적 생성자 (같은 Bitmap.FromFile)도 옵션입니다
BlueRaja-Danny Pflughoeft


2
@Laiv 뭔가 빠졌습니까? 그것들은 같은 방식으로 사용되므로 동일한 서명을 갖습니다. 참조를 검색하고 발신자가 생각한 것을 말할 수 없습니다. OP가 두 번째 주장을 해야하는지 여부를 언급하는 것처럼 들리지만 OP가 요구하는 것은 아닙니다 (그리고 그들은 때때로 두 가지가 모두 필요하다는 것을 확신 할 수 있습니다.
Kat

2
@Voo Openedge | Progress 10.2B 용 컴파일러는 무시합니다. 끊임없는 분석법 변경 전략을 거의 죽였습니다. 대신 같은 효과를 내기 위해 오버로딩을 사용해야했습니다.
브렛

답변:


24

기본값보다 여러 생성자를 선호하며 개인적으로 두 생성자 예제가 마음에 들지 않으므로 다르게 구현해야합니다.

여러 생성자를 사용하는 이유는 기본 매개 변수가 모든 매개 변수가 null이 아니고 유효한지 여부를 확인할 수 있고 다른 생성자가 기본 매개 변수의 기본값을 제공 할 수 있기 때문입니다.

그러나 예제에서는 보조 생성자조차도 null기본값으로 a를 전달 하고 기본 생성자도 기본값을 알아야 하므로 차이가 없습니다 . 나는 그렇게해서는 안된다고 생각합니다.

이것은 다음과 같이 구현하면 깨끗하고 잘 분리된다는 것을 의미합니다.

public DelegateCommand(Action<T> execute) : this(execute, _ => true) { }

public DelegateCommand(Action<T> execute, Func<T, bool> canExecute)
{
    this.execute = execute ?? throw new ArgumentNullException(..);
    this.canExecute = canExecute ?? throw new ArgumentNullException(..);
}

통지 _ => true이제 모든 매개 변수를 확인하는 중입니다 기본 생성자에 전달 null하고 기본값에 대해 상관하지 않는다.


그러나 가장 중요한 점은 확장 성입니다. 나중에 코드를 확장 할 가능성이있는 경우 여러 생성자가 더 안전합니다. 필요한 매개 변수를 더 추가하고 선택 매개 변수가 끝에 와야하는 경우 현재 구현을 모두 해제합니다. 이전 생성자를 [Obsolete]만들고 사용자에게 코드가 즉시 중단되지 않고 새 구현으로 마이그레이션 할 시간을 제공하여 제거 될 것이라고 알릴 수 있습니다 .


반면에 너무 많은 매개 변수를 선택적으로 만들면 혼동 될 수 있습니다. 한 시나리오에서 일부는 필요하고 다른 시나리오에서는 선택적으로 필요한 경우 단순히 매개 변수를 보면서 올바른 생성자를 선택하는 대신 문서를 연구해야하기 때문입니다.


12
반면에 너무 많은 매개 변수를 선택적으로 선택하는 것은 혼란 스러울 수 있습니다 ... 솔직히 말해서 너무 많은 매개 변수를 갖는 것은 선택적인지 아닌지에 관계없이 혼란 스럽습니다.
Andy

1
@DavidPacker 나는 당신에게 동의하지만, 너무 많은 매개 변수가 너무 많은 것은 또 다른 이야기입니다; ;-)
t3chb0t

2
매개 변수를 생략하는 생성자와 매개 변수의 기본값이있는 생성자를 갖는 것에는 또 다른 차이점이 있습니다. 첫 번째 경우, 호출자는 명시 적으로 매개 변수 전달을 피할 수있는 반면, 후자의 경우 호출자가 할 수 없습니다. 매개 변수를 전달하지 않으면 기본값을 전달하는 것과 같습니다. 생성자가이 구분을해야하는 경우 두 개의 생성자가 유일한 방법입니다.
게리 맥길

1
예를 들어, 문자열을 형식화하는 클래스가 있다고 가정하고 선택적 으로 CultureInfo객체로 구성 할 수 있습니다 . 나는 허용 된 API를 선호하는 CultureInfo매개 변수가 추가 매개 변수를 통해 제공 할 수 있지만,이 경우 주장 후 공급은해야 하지 수를 null. 그렇게하면 우연한 null값이 "없음"을 의미하는 것으로 잘못 해석되지 않습니다.
게리 맥길

확장 성이 실제로 선택적 매개 변수 대한 이유인지 확실하지 않습니다 . 매개 변수가 필요하고 매개 변수 수를 변경 Obsolete한 경우 선택적 매개 변수가 있든 없든 상관없이 새로운 구성 요소를 만들고 이전 구성 요소를 손상시키지 않으려면 이전 생성자를 만들어야합니다 . 선택적 매개 변수를 사용하면 하나만 Obsolete제거 하면됩니다 .
Herohtar

17

생성자에서 수행하는 유일한 작업은 간단한 할당이라고 생각하면 단일 생성자 솔루션이 더 나은 선택 일 수 있습니다. 다른 생성자는 추가 기능을 제공하지 않으며 두 번째 매개 변수를 제공 할 필요가 없다는 두 개의 매개 변수가있는 생성자의 설계에서 분명합니다.

여러 유형의 객체를 생성 할 때 여러 생성자가 의미가 있습니다. 이 경우, 생성자는 입력 매개 변수를 처리하고 구성중인 클래스의 올바른 내부 특성 표시로 형식화하기 때문에 외부 팩토리를 대체합니다. 그러나 귀하의 경우에는 발생하지 않으므로 단일 생성자로 충분해야합니다.


3

각 접근법이 빛날 수있는 두 가지 사례가 있다고 생각합니다.

첫째, 간단한 생성자가있을 때 (일반적으로 경험에 따라) 선택적 인수를 고려할 것입니다.

  1. 그것들은 작성되어야 할 코드를 최소화해야합니다.
  2. 문서가 한 곳에 있고 반복되지 않는지 확인할 수 있습니다 (오래된 추가 영역이 열리기 때문에 나쁩니다).
  3. 선택적인 인수가 많으면 생성자 조합이 매우 혼동되지 않도록 할 수 있습니다. 별개로 오버로드 된 생성자를 원한다면 4 개의 생성자 (버전이없는 버전, 버전이있는 버전 및 버전이 모두있는 버전)가 있어야합니다. 이것은 분명히 확장 성이 좋지 않습니다.

그러나 생성자의 선택적 인수가 상황을 더 혼란스럽게 만드는 경우가 있습니다. 명백한 예는 이러한 선택적 인수가 배타적 일 때입니다 (즉, 함께 사용할 수 없음). 실제로 유효한 인수 조합 만 허용하는 오버로드 된 생성자가 있으면이 제한 조건의 컴파일 시간이 적용됩니다. 즉,이 경우 (예 : 각 클래스가 독점적 인 동작을 수행하는 기본에서 상속되는 여러 클래스의 경우)도 발생하지 않아야합니다.


여러 개의 선택적 매개 변수가있는 순열 폭발을 언급하면 ​​+1입니다.
Jpsy
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.