Programming

C # 4.0에서 메서드 오버로드 및 선택적 매개 변수

procodes 2020. 7. 23. 21:00
반응형

C # 4.0에서 메서드 오버로드 및 선택적 매개 변수


어느 것이 더 낫습니까? 한 눈에 옵션 매개 변수가 더 좋아 보이지만 (코드가 적고 XML 문서가 적음) 대부분의 MSDN 라이브러리 클래스가 선택적 매개 변수 대신 오버로드를 사용하는 이유는 무엇입니까?선택적 매개 변수 (또는 과부하)를 사용할 때주의해야 할 사항이 있습니까?


C # 4.0의 'Named Parameters'와 함께 'Optional parameters'를 사용하는 좋은 사례는 매개 변수 수에 따라 메서드를 오버로드하는 메서드 오버로드에 대한 우아한 대안을 제시한다는 것입니다.예를 들어 당신이 방법은 싶은 말

foo

과 같이 사용 / 호출 할 수,

foo()

,

foo(1)

,

foo(1,2)

,

foo(1,2, "hello")

. 메소드 오버로드를 사용하면 다음과 같은 솔루션을 구현할 수 있습니다.

///Base foo method
public void DoFoo(int a, long b, string c)
{
   //Do something
}  

/// Foo with 2 params only
public void DoFoo(int a, long b)
{
    /// ....
    DoFoo(a, b, "Hello");
}

public void DoFoo(int a)
{
    ///....
    DoFoo(a, 23, "Hello");
}

.....

C # 4.0의 선택적 매개 변수를 사용하면 다음과 같은 사용 사례를 구현할 수 있습니다.

public void DoFoo(int a = 10, long b = 23, string c = "Hello")

그런 다음과 같은 방법을 사용할 수 있습니다-명명 된 매개 변수의 사용에 유의하십시오-

DoFoo(c:"Hello There, John Doe")

이 호출은 매개 변수

a

값을 10으로, 매개 변수

b

를 23으로 사용합니다.이 호출의 또 다른 변형-매개 변수 값이 메소드 서명에 나타나는 순서대로 설정하지 않아도됩니다. 명명 된 매개 변수는 값을 명시 적으로 만듭니다.

DoFoo(c:"hello again", a:100) 

명명 된 매개 변수를 사용하면 얻을 수있는 또 다른 이점은 가독성이 크게 향상되어 선택적 매개 변수 메서드의 코드 유지 관리가 향상된다는 것입니다.하나의 메소드가 메소드 오버로드에서 3 개 이상의 메소드를 정의해야하는 중복을 작성하는 방법에 유의하십시오. 내가 찾은 이것은 명명 된 매개 변수와 함께 선택적 매개 변수를 사용하는 좋은 사용 사례입니다.


선택적 매개 변수는 API로 공개적으로 노출 할 때 문제를 제공합니다. 매개 변수 이름을 바꾸면 문제가 발생할 수 있습니다. 기본값을 변경하면 문제가 발생합니다 (예 : 일부 정보

는 C # 4.0의 선택적 매개 변수 경고

참조 ).또한 선택적 params는 컴파일 타임 상수에만 사용할 수 있습니다. 이것을 비교하십시오 :

public static void Foo(IEnumerable<string> items = new List<string>()) {}
// Default parameter value for 'items' must be a compile-time constant

이에

public static void Foo() { Foo(new List<string>());}
public static void Foo(IEnumerable<string> items) {}
//all good

최신 정보

다음은 기본 매개 변수

있는 생성자 가 Reflection과 함께 잘 재생되지 않을 때 추가로 읽을 수있는 자료 입니다.


나는 그들이 다른 목적을 수행한다고 생각합니다. 선택적 매개 변수는 매개 변수에 기본값을 사용할 수있는 경우를위한 것이며 기본 코드는 동일합니다.

public CreditScore CheckCredit( 
  bool useHistoricalData = false,  
  bool useStrongHeuristics = true) { 
  // ... 
}

메소드 오버로드는 상호 배타적 (서브 세트) 매개 변수가있는 경우에 사용됩니다. 이는 일반적으로 일부 매개 변수를 사전 처리해야하거나 메소드의 다른 "버전"에 대해 서로 다른 코드를 가지고 있음을 의미합니다 (이 경우에도 일부 매개 변수를 공유 할 수 있으므로 위에서 "서브 세트"를 언급 한 이유). :

public void SendSurvey(IList<Customer> customers, int surveyKey) {  
  // will loop and call the other one 
} 
public void SendSurvey(Customer customer, int surveyKey) {  
  ...  
}

(나는 얼마 전에

여기

에 대해 썼다 )


이것은 거의 말없이 진행되지만,모든 언어가 선택적 매개 변수를 지원하는 것은 아닙니다. 라이브러리가 해당 언어에 익숙해 지도록하려면 과부하를 사용해야합니다.

Granted, this isn't even an issue for most shops. But you can bet it's why Microsoft doesn't use optional parameters in the Base Class Library.


Optional parameters has to be last. So you can not add an extra parameter to that method unless its also optional. Ex:

void MyMethod(int value, int otherValue = 0);

If you want to add a new parameter to this method without overloading it has to be optional. Like this

void MyMethod(int value, int otherValue = 0, int newParam = 0);

If it can't be optional, then you have to use overloading and remove the optional value for 'otherValue'. Like this:

void MyMethod(int value, int otherValue = 0);
void MyMethod(int value, int otherValue, int newParam);

I assume that you want to keep the ordering of the parameters the same.

So using optional parameters reduces the number of methods you need to have in your class, but is limited in that they need to be last.

Update When calling methods with optional parameters, you can used named parameters like this:

void MyMethod(int value, int otherValue = 0, int newValue = 0);

MyMethod(10, newValue: 10); // Here I omitted the otherValue parameter that defaults to 0

So optional parameters gives the caller more possibilities.

One last thing. If you use method overloading with one implementation, like this:

void MyMethod(int value, int otherValue)
{
   // Do the work
}

void MyMethod(int value)
{
   MyMethod(value, 0); // Do the defaulting by method overloading
}

Then when calling 'MyMethod' like this:

MyMethod(100); 

Will result in 2 method calls. But if you use optional parameters there is only one implementation of 'MyMethod' and hence, only one method call.


Neither is definitively "better" than the other. They both have their place in writing good code. Optional parameters should be used if the parameters can have a default value. Method overloading should be used when the difference in signature goes beyond not defining parameters that could have default values (such as that the behavior differs depending on which parameters are passed, and which are left to the default).

// this is a good candidate for optional parameters
public void DoSomething(int requiredThing, int nextThing = 12, int lastThing = 0)

// this is not, because it should be one or the other, but not both
public void DoSomething(Stream streamData = null, string stringData = null)

// these are good candidates for overloading
public void DoSomething(Stream data)
public void DoSomething(string data)

// these are no longer good candidates for overloading
public void DoSomething(int firstThing)
{
    DoSomething(firstThing, 12);
}
public void DoSomething(int firstThing, int nextThing)
{
    DoSomething(firstThing, nextThing, 0);
}
public void DoSomething(int firstThing, int nextThing, int lastThing)
{
    ...
}

A good place to use optional parameter is WCF since it does not support method overloading.


What about a 3rd option: pass an instance of a class with properties corresponding to various "optional parameters".

This provides the same benefit as named and optional parameters, but I feel that this is often much clearer. It gives you an opportunity to logically group parameters if necessary (i.e. with composition) and encapsulate some basic validation as well.

Also, if you expect clients that consume your methods to do any kind of metaprogramming (such as building linq expressions involving your methods), I think that keeping the method signature simple has its advantages.


This is not really an answer to the original question, but rather a comment on @NileshGule's answer, but:

a) I don't have enough reputation points to comment

b) Multiple lines of code is quite hard to read in comments

Nilesh Gule wrote:

One benefit of using optional parameters is that you need not have to do a conditional check in your methods like if a string was null or empty if one of the input parameter was a string. As there would be a default value assigned to the optional parameter, the defensive coding will be reduced to a great extent.

This is actually incorrect, you still have to check for nulls:

void DoSomething(string value = "") // Unfortunately string.Empty is not a compile-time constant and cannot be used as default value
{
  if(value == null)
    throw new ArgumentNullException();
}

DoSomething(); // OK, will use default value of ""
DoSomething(null); // Will throw

If you supply a null string reference, it will not be replaced by the default value. So you still need to check the input parameters for nulls.


One benefit of using optional parameters is that you need not have to do a conditional check in your methods like if a string was null or empty if one of the input parameter was a string. As there would be a default value assigned to the optional parameter, the defensive coding will be reduced to a great extent.

Named parameters give the flexibility of passing parameter values in any order.


To address your first question,

why do most MSDN library classes use overloading instead of optional parameters?

It is for backward compatibility.

When you open a C# 2, 3.0 or 3.5 project in VS2010, it is automatically upgraded.

Just imagine the inconvenience it would create if each of the overloads used in the project had to be converted to match the corresponding optional parameter declaration.

Besides, as the saying goes, "why fix what is not broken?". It is not necessary to replace overloads that already work with new implementations.

참고URL : https://stackoverflow.com/questions/3316402/method-overloading-vs-optional-parameter-in-c-sharp-4-0

반응형