문제

다음과 같은 params object[]를 사용하는 메서드가 있습니다.

void Foo(params object[] items)
{
    Console.WriteLine(items[0]);
}

이 메서드에 두 개의 개체 배열을 전달하면 제대로 작동합니다.

Foo(new object[]{ (object)"1", (object)"2" }, new object[]{ (object)"3", (object)"4" } );
// Output: System.Object[]

그러나 단일 object[]를 전달하면 내 object[]를 첫 번째 매개변수로 사용하지 않고 대신 하나씩 전달하려는 것처럼 모든 요소를 ​​사용합니다.

Foo(new object[]{ (object)"1", (object)"2" });
// Output: 1, expected: System.Object[]

단일 object[]를 params 배열의 첫 번째 인수로 어떻게 전달합니까?

도움이 되었습니까?

해결책

간단한 타입캐스트를 통해 컴파일러는 이 경우의 의미를 알 수 있습니다.

Foo((object)new object[]{ (object)"1", (object)"2" }));

배열은 객체의 하위 유형이므로 이 모든 것이 작동합니다.조금 이상한 해결책이지만 동의하겠습니다.

다른 팁

그만큼 params 매개변수 수정자는 호출자에게 여러 인수를 메서드에 전달하기 위한 간단한 구문을 제공합니다.메소드를 호출하는 방법에는 두 가지가 있습니다. params 매개변수:

1) 매개변수 유형의 배열을 사용하여 호출합니다. 이 경우 params 키워드는 효과가 없으며 배열은 메소드에 직접 전달됩니다.

object[] array = new[] { "1", "2" };

// Foo receives the 'array' argument directly.
Foo( array );

2) 또는 확장된 인수 목록을 사용하여 호출하면 컴파일러가 자동으로 인수 목록을 임시 배열로 래핑하고 이를 메서드에 전달합니다.

// Foo receives a temporary array containing the list of arguments.
Foo( "1", "2" );

// This is equivalent to:
object[] temp = new[] { "1", "2" );
Foo( temp );


객체 배열을 "params object[]" 매개변수를 사용하면 다음 중 하나를 수행할 수 있습니다.

1) 래퍼 배열을 수동으로 생성하고 언급한 대로 메서드에 직접 전달합니다. 라세브크:

Foo( new object[] { array } );  // Equivalent to calling convention 1.

2) 또는 인수를 다음으로 캐스팅하세요. object, 에서 언급했듯이 아담, 이 경우 컴파일러는 래퍼 배열을 생성합니다.

Foo( (object)array );  // Equivalent to calling convention 2.


그러나 메서드의 목표가 여러 개체 배열을 처리하는 것이라면 명시적인 "params object[][]" 매개변수입니다.이렇게 하면 여러 배열을 인수로 전달할 수 있습니다.

void Foo( params object[][] arrays ) {
  foreach( object[] array in arrays ) {
    // process array
  }
}

...
Foo( new[] { "1", "2" }, new[] { "3", "4" } );

// Equivalent to:
object[][] arrays = new[] {
  new[] { "1", "2" },
  new[] { "3", "4" }
};
Foo( arrays );

편집하다: Raymond Chen은 이 동작과 이것이 C# 사양과 어떻게 관련되는지 설명합니다. 새 게시물.

이것은 LINQ와 관련된 한 줄 솔루션입니다.

var elements = new String[] { "1", "2", "3" };
Foo(elements.Cast<object>().ToArray())

다음과 같이 다른 object[] 배열로 캡슐화해야 합니다.

Foo(new Object[] { new object[]{ (object)"1", (object)"2" }});

한 가지 옵션은 이를 다른 배열로 래핑할 수 있다는 것입니다.

Foo(new object[]{ new object[]{ (object)"1", (object)"2" } });

좀 추악하지만 각 항목이 배열이므로 문제를 해결하기 위해 캐스팅할 수는 없습니다...예를 들어 Foo(params object items)인 경우 다음과 같이 할 수 있습니다.

Foo((object) new object[]{ (object)"1", (object)"2" });

또는 단일 배열만 사용하는 Foo의 또 다른 오버로드된 인스턴스를 정의해 볼 수도 있습니다.

void Foo(object[] item)
{
    // Somehow don't duplicate Foo(object[]) and
    // Foo(params object[]) without making an infinite
    // recursive call... maybe something like
    // FooImpl(params object[] items) and then this
    // could invoke it via:
    // FooImpl(new object[] { item });
}
new[] { (object) 0, (object) null, (object) false }

이 문제를 해결하는 또 다른 방법은 다음과 같습니다(좋은 방법은 아니지만 보기에는 좋습니다).

static class Helper
{
    public static object AsSingleParam(this object[] arg)
    {
       return (object)arg;
    }
}

용법:

f(new object[] { 1, 2, 3 }.AsSingleParam());
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top