[c#] C # 4.0에서 오버로드 또는 선택적 매개 변수를 사용하여 메서드를 선언해야합니까?

Anders의 C # 4.0 및 C # 5.0 미리보기에 대한 이야기를 보고 있었는데 , C #에서 선택적 매개 변수를 사용할 수있을 때 모든 매개 변수를 지정할 필요가없는 메소드를 선언하는 데 권장되는 방법이 무엇인지 생각하게되었습니다.

예를 들어, FileStream클래스 와 같은 것에 는 논리적 ‘패밀리’로 나눌 수있는 약 15 개의 다른 생성자가 있습니다. 예를 들어 문자열에서 아래의 것, an IntPtr의 것, SafeFileHandle.

FileStream(string,FileMode);
FileStream(string,FileMode,FileAccess);
FileStream(string,FileMode,FileAccess,FileShare);
FileStream(string,FileMode,FileAccess,FileShare,int);
FileStream(string,FileMode,FileAccess,FileShare,int,bool);

이 유형의 패턴은 3 개의 생성자를 대신 사용하고 기본값으로 설정할 수있는 매개 변수에 대해 선택적 매개 변수를 사용하여 단순화 할 수있는 것 같습니다. 이렇게하면 생성자의 다른 패밀리가 더 뚜렷해집니다. [참고 :이 변경 사항은 BCL에서 만든, 나는 이러한 유형의 상황에 대해 가상으로 이야기하고 있습니다].

어떻게 생각해? C # 4.0부터는 밀접하게 관련된 생성자 및 메서드 그룹을 선택적 매개 변수가있는 단일 메서드로 만드는 것이 더 합리적일까요? 아니면 기존의 많은 오버로드 메커니즘을 고수해야 할 좋은 이유가 있습니까?



답변

다음을 고려합니다.

  • 선택적 매개 변수를 지원하지 않는 언어에서 코드를 사용해야합니까? 그렇다면 과부하 포함을 고려하십시오.
  • 팀에 선택적 매개 변수를 강력하게 반대하는 구성원이 있습니까? (때때로 사건을 주장하는 것보다 마음에 들지 않는 결정으로 사는 것이 더 쉽습니다.)
  • 코드 빌드간에 기본값이 변경되지 않을 것이라고 확신합니까? 아니면 가능하다면 호출자가 괜찮을까요?

기본값이 어떻게 작동하는지 확인하지는 않았지만 기본값이 const필드에 대한 참조와 거의 동일하게 호출 코드에 구워 진다고 가정 합니다. 일반적으로 괜찮습니다. 기본값에 대한 변경은 어쨌든 상당히 중요하지만 고려해야 할 사항입니다.


답변

메서드 오버로드가 일반적으로 다른 수의 인수로 동일한 작업을 수행하면 기본값이 사용됩니다.

메서드 오버로드가 매개 변수에 따라 다른 기능을 수행하면 오버로딩이 계속 사용됩니다.

VB6 일에 선택 사항을 사용했고 그 이후로 놓쳤으므로 C #에서 XML 주석 중복을 많이 줄일 수 있습니다.


답변

저는 선택적 매개 변수와 함께 Delphi를 영원히 사용해 왔습니다. 대신 과부하를 사용하도록 전환했습니다.

더 많은 오버로드를 만들려고 할 때 선택적 매개 변수 형식과 항상 충돌하므로 어쨌든 비 옵션으로 변환해야합니다.

그리고 저는 일반적으로 하나의 슈퍼 메서드가 있고 나머지는 그 주위에 더 간단한 래퍼 라는 개념이 마음에 듭니다 .


답변

4.0의 선택적 매개 변수 기능을 확실히 사용할 것입니다. 그것은 어리석은 것을 제거합니다 …

public void M1( string foo, string bar )
{
   // do that thang
}

public void M1( string foo )
{
  M1( foo, "bar default" ); // I have always hated this line of code specifically
}

… 발신자가 볼 수있는 곳에 값을 넣습니다.

public void M1( string foo, string bar = "bar default" )
{
   // do that thang
}

훨씬 더 간단하고 오류 발생 가능성이 훨씬 적습니다. 나는 실제로 이것을 과부하 사례의 버그로 보았습니다 …

public void M1( string foo )
{
   M2( foo, "bar default" );  // oops!  I meant M1!
}

나는 아직 4.0 컴파일러를 가지고 놀지 않았지만 컴파일러가 단순히 당신을 위해 과부하를 방출한다는 것을 알고 충격을받지 않을 것입니다.


답변

선택적 매개 변수는 기본적으로 메서드 호출을 처리하는 컴파일러가 호출 사이트에 적절한 기본값을 삽입하도록 지시하는 메타 데이터입니다. 반대로, 오버로드는 컴파일러가 여러 메서드 중 하나를 선택할 수있는 수단을 제공하며, 그중 일부는 기본값을 제공 할 수 있습니다. 옵션 매개 변수를 지원하지 않는 언어로 작성된 코드에서 선택적 매개 변수를 지정하는 메소드를 호출하려는 경우 컴파일러는 “선택적”매개 변수를 지정해야하지만 선택적 매개 변수를 지정하지 않고 메소드를 호출하면 다음과 같습니다. 기본값과 동일한 매개 변수를 사용하여 호출하는 것과 동일하므로 이러한 메서드를 호출하는 언어에는 장애물이 없습니다.

호출 사이트에서 선택적 매개 변수 바인딩의 중요한 결과는 컴파일러에서 사용할 수있는 대상 코드의 버전에 따라 값이 할당된다는 것입니다. 어셈블리 에 기본값이 5 인 Foo메서드 Boo(int)가 있고 어셈블리 Bar에에 대한 호출이 포함 된 Foo.Boo()경우 컴파일러는이를 Foo.Boo(5). 기본값 어셈블리 (6)로 변경하고 경우 Foo다시 컴파일, Bar전화를 계속 Foo.Boo(5)이의 새로운 버전으로 다시 컴파일 될 때까지하지 않는 나 Foo. 따라서 변경 될 수있는 항목에 대해 선택적 매개 변수를 사용하지 않아야합니다.


답변

선택적 인수 또는 오버로드를 사용해야하는지 여부가 논쟁의 여지가 있지만 가장 중요한 것은 각각 대체 할 수없는 고유 한 영역이 있다는 것입니다.

선택적 인수는 명명 된 인수와 함께 사용할 때 COM 호출의 모든 옵션이 포함 된 긴 인수 목록과 결합 할 때 매우 유용합니다.

오버로드는 메소드가 여러 다른 인수 유형 (예제 중 하나)에서 작동 할 수 있고 예를 들어 내부적으로 캐스팅 할 때 매우 유용합니다. 의미가있는 데이터 유형 (기존 오버로드에 의해 허용됨)을 제공하기 만하면됩니다. 선택적 인수로는 이길 수 없습니다.


답변

나는 기본값이 메소드에 더 가까운 것을 유지하기 때문에 선택적 매개 변수를 기대하고 있습니다. 따라서 “expanded”메서드를 호출하는 오버로드에 대한 수십 줄 대신 메서드를 한 번만 정의하면 메서드 서명에서 선택적 매개 변수의 기본값을 확인할 수 있습니다. 차라리 다음을보고 싶습니다.

public Rectangle (Point start = Point.Zero, int width, int height)
{
    Start = start;
    Width = width;
    Height = height;
}

대신 :

public Rectangle (Point start, int width, int height)
{
    Start = start;
    Width = width;
    Height = height;
}

public Rectangle (int width, int height) :
    this (Point.Zero, width, height)
{
}

분명히이 예제는 매우 간단하지만 5 개의 과부하가있는 OP의 경우 상황이 매우 빠르게 혼잡해질 수 있습니다.