무제한 매개 변수가있는 c # 메소드 또는 배열 또는 목록이있는 메소드?


21

최근에 무제한 매개 변수를 사용하여 몇 가지 방법을 만들 수 있다는 것을 배웠습니다.

SomeMethod(params int[] numbers);

그러나 내 질문은, 그 점과 목록이나 배열을받는 메소드를 만드는 것의 차이점은 무엇입니까?

SomeMethod(int[] numbers);
SomeMethod(List<int> numbers);

아마도 성능에 영향을 줄 수 있습니까? 나는 당신이 무제한 매개 변수를 가진 것을 선호하는 방식을 완전히 이해하거나 보지 못합니다.

Google의 빠른 검색이 도움이되지 않았습니다. 도와 드리겠습니다.



내 대답은 아래에 더하여, params또한 필요 배열로 인수의 유형입니다. 배열 이외의 컬렉션을 사용해야하는 경우 params인수가 아닌 것을 제공하는 것이 더 합리적 일 수 있습니다 .
digitlworld

1
@digitlworld :이 주제에 관심이 있으시면 github.com/dotnet/csharplang/issues/179 를 참조하십시오 .
Eric Lippert

의 서명 및 / 또는 구현을보십시오 Console.Write.
3

답변:


27

그 점과 목록이나 배열을받는 메소드를 만드는 것의 차이점은 무엇입니까?

차이점

void M(params int[] x)

void N(int[] x)

M이 다음과 같이 호출 될 수 있다는 것입니다.

M(1, 2, 3)

또는 이와 같이 :

M(new int[] { 1, 2, 3 });

그러나 N은 첫 번째 방법이 아닌 두 번째 방법으로 만 호출 될 수 있습니다 .

아마도 성능에 영향을 줄 수 있습니까?

성능에 미치는 영향 M은 첫 번째 방식으로 호출하든 두 번째 방식으로 호출하든 배열을 생성하는 방식입니다. 어레이를 만들면 시간과 메모리가 모두 필요하므로 성능에 영향을줍니다. 성능 영향은 성능 목표와 비교하여 측정해야합니다. 추가 어레이를 생성하는 비용이 시장에서의 성공과 실패의 차이 인 게이팅 요소 일 가능성은 낮습니다.

나는 당신이 무제한 매개 변수를 가진 것을 선호하는 방식을 완전히 이해하거나 보지 못합니다.

메소드를 호출하는 코드 작성자에게는 순수하고 전적으로 편리합니다. 그것은 단순히 짧고 쉽게 쓰기에

M(1, 2, 3);

글쓰기 대신

M(new int[] { 1, 2, 3 });

발신자 측에서 몇 번의 키 입력 만 저장하면됩니다. 그게 다야

묻지 않았지만 다음에 대한 답을 알고 싶은 몇 가지 질문이 있습니다.

이 기능은 무엇입니까?

호출자 측에 가변 개수의 인수를 전달할 수있는 메소드를 variadic 이라고 합니다 . Params 메소드는 C #이 가변 방식을 구현하는 방법입니다.

다양한 방법으로 과부하 해결이 어떻게 작동합니까?

오버로드 해결 문제가 발생하면 C #은 "정상"및 "확장"형식을 모두 고려하고, 해당되는 경우 "정상"형식이 항상 우선합니다. 예를 들어 다음을 고려하십시오.

void P(params object[] x){}

우리는 전화를

P(null);

적용 가능한 두 가지 가능성이 있습니다. "정상적인"형식 P에서 배열에 대한 null 참조를 호출 하고 전달합니다. "확장 된"형태로을 호출 P(new object[] { null })합니다. 이 경우 정상적인 형태가 이깁니다. 우리가 전화를 P(null, null)했다면 일반 양식은 적용 할 수 없으며 기본적으로 확장 양식이 승리합니다.

도전 과제 : var s = new[] { "hello" };전화를 했다고 가정 해 봅시다 P(s);. 콜 사이트에서 어떤 일이 발생하는지 그리고 그 이유를 설명하십시오. 당신은 놀라게 될 것입니다!

도전 과제 : void P(object x){}void P(params object[] x){}. 무엇을 P(null)하고 왜?

도전 과제 : void M(string x){}void M(params string[] x){}. 무엇을 M(null)하고 왜? 이것이 이전 사례와 어떻게 다릅니 까?


채널 2 : P(null)P((object)null)P((object[])null)- 어디 이러한 차이에 대한 설명을 찾을 수 있습니까? 그것은 느낌 처럼 null한 일부 특수한 유형의 배열이 아닌 객체 (로 변환, P(null)문자열 또는 모호한 문자열 (배열로 변환을 찾을 수), 그러나 M(null)아주 이상한 느낌이 ...),이 중 두 경우 모두 모호하거나 선택하는 기대 단일 인수 버전 (그렇지 않음). 그러나 C ++ 템플릿의 범용 참조 ( ) 와 같이 params어쨌든 일반적&& 이기 때문에 더 일치합니다 (Ch3이 아닌 Ch2).
firda

@ firda : C # 사양에서 설명을 찾을 수 있습니다. 이상한 이유는 다음과 같습니다. null은 object, string, object [] 및 string []로 변환 할 수 있습니다. 그렇다면 과부하 해결에 대한 의문은 다음과 같습니다. 어떤 변환이 가장 좋습니까? 이 경우 제어 규칙은 일반보다 낫습니다 . 어떤 유형이 더 구체적인지 어떻게 알 수 있습니까? 규칙은 : 모든 기린은 동물이지만 모든 동물이 기린은 아니지만 기린은 동물보다 더 구체적입니다. 모든 object[]있습니다 object,하지만 모든되지 object이다 object[], 따라서 object[]더 구체적이다.
Eric Lippert

@ firda : 이제 문자열이 모호한 이유를 알았습니다. "모든 것은 사실이 아니다 string[]있습니다 string." 사실 NO string[]없습니다 string와 NO가 string있습니다 string[]때문에, string보다 구체적인 또는보다 일반적으로하지 않습니다 string[], 그리고 선택하라는 메시지가 표시 될 때 우리는 모호성 오류가 발생합니다.
Eric Lippert

모두 object[]object... object[]더 구체적 이므로 P(null)더 구체적인 배열 인 thx로갑니다. 여기에 몇 가지 규칙이 있습니다. docs.microsoft.com/en-us/dotnet/csharp/language-reference/…
firda

5

작은 프로토 타입을 만들었습니다. 그 대답 params은 배열을 통과하기위한 단순한 구문 설탕 인 것처럼 보입니다 . 정말 놀라운 일이 아닙니다. 동일한 메소드의 두 가지 버전을 만들었는데 유일한 차이점은 "params"키워드입니다. a System.ParamArrayAttributeparams버전 에 적용 되었다는 점을 제외하고 두 가지 모두에 대해 생성 된 IL은 동일했습니다 .

또한 호출 사이트에서 생성 된 IL은 수동 선언으로 메소드를 new int[]호출하는 것과 params인수를 사용하여 메소드를 호출하는 것 사이에서 동일했습니다 .

따라서 대답은 "편의성"인 것 같습니다. 성능에 차이가없는 것 같습니다. params대신 배열을 사용 하여 함수를 호출 할 수도 있으므로 놀랍지 않습니다. 메소드의 소비자 someMethod(1, 2, 3)가 항상 콜렉션을 먼저 작성해야하는 것 (예 :) 보다 많은 수의 매개 변수 (예 :)로 메소드를 호출하는 것이 더 쉬운 경우 가됩니다 someMethod(new List<int>() { 1, 2, 3 } ).


4

무제한 매개 변수의 기능은 많은 시나리오에서 다음과 같은 이점을 제공합니다.

  1. 느슨한 결합
  2. 재사용 성 향상
  3. 응용 프로그램의 전반적인 성능 향상

다음은 무제한 매개 변수 옵션이 좋은 예입니다.

이메일 전송을위한 응용 프로그램을 구축해야합니다.

이메일을 보내는 기능은 'To', 'CC'및 'BCC'필드의 단일 또는 다중 값을 처리 할 수 ​​있어야합니다.

매개 변수 유형이 모든 필드 (To, CC, BCC)의 배열 또는 목록으로 고정 된 경우, 호출 기능은 이메일 발신자 기능을 호출하기 위해 3 개의 배열 또는 목록을 정의하는 모든 복잡성을 처리해야합니다. .

발신자가 하나의 주소로만 이메일을 보내려고하더라도 이메일 발신자 기능은 호출자가 3 개의 서로 다른 배열을 매개 변수로 정의하고 보내도록합니다.

이메일 발신자 기능이 무제한 매개 변수 접근 방식을 취하면 발신자 기능이 모든 복잡성을 처리 할 필요는 없습니다.

무제한 매개 변수 접근 방식은 불필요한 곳에서 배열이나 목록을 만들지 않아 응용 프로그램의 런타임 성능을 향상시킵니다.


2

A로부터 비 성능 , 스타일 관점의 params키워드는 매개 변수의 선택 목록을 보낼 때이 정말 좋다.

개인적으로 params코드가 다음과 같을 때 사용합니다.

SomeMethod('Option1', 'Option17');

void SomeMethod(params string[] options)
{
    foreach(var option in options)
    {
        switch(option): ...
    }
}

이것에 대한 좋은 부분은 매번 배열이나 목록을 만들지 않고도이 방법을 사용할 수 있다는 것입니다.

내가 사용 array하거나 list알고있을 때 항상이 기능을 이미 함께 묶어 놓은 일련의 데이터를 전달할 것입니다.

List<User> users = GetUsersFromDB();
SomeMethod(users);

params유연성이 향상되는 이점이 있습니다. 코드에 상대적으로 작은 영향을 줄 수 있지만 여전히 유용한 도구입니다.


1

전화 규칙이 다릅니다. 예를 들어 ...

public class Test
{
    public void Method1( params int[] nums )
    {
        nums.ToList().ForEach( n => Console.WriteLine(n) );
    }

    public void Method2( List<int> nums )
    {
        nums.ForEach( n  => Console.WriteLine(n) );
    }   
}

void Main()
{   
    var t = new Test();
    t.Method1( 1, 2, 3, 4 );
    t.Method2( new List<int>() { 1, 2, 3, 4 } );
}

첫 번째 경우 메서드에 별도의 매개 변수만큼 많은 정수를 전달할 수 있습니다. 두 번째로, 목록을 인스턴스화하고 전달해야합니다.

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