126

次のような params object[] を取るメソッドがあります。

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

このメソッドに 2 つのオブジェクト配列を渡すと、正常に動作します。

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

しかし、単一の object[] を渡すと、object[] を最初のパラメーターとして使用せず、代わりに、1 つずつ渡したかったようにすべての要素を受け取ります。

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

単一の object[] を最初の引数として params 配列に渡すにはどうすればよいですか?

4

7 に答える 7

102

単純な型キャストにより、この場合の意味をコンパイラーが認識できるようになります。

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

配列はオブジェクトのサブタイプであるため、これはすべてうまくいきます。少し奇妙な解決策ですが、同意します。

于 2008-08-30T21:36:59.377 に答える
76

パラメーター修飾子は、params複数の引数をメソッドに渡すためのショートカット構文を呼び出し元に提供します。paramsパラメータを指定してメソッドを呼び出すには、次の 2 つの方法があります。

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) lassevkで言及されているように、ラッパー配列を手動で作成し、それをメソッドに直接渡します。

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

2)または、 Adamobjectが述べたように、引数を にキャストします。この場合、コンパイラはラッパー配列を作成します。

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# 仕様とどのように関連しているかについて、新しい投稿で説明しています。

于 2008-09-01T16:28:37.793 に答える
3

次のように、別の object[] 配列にカプセル化する必要があります。

Foo(new Object[] { new object[]{ (object)"1", (object)"2" }});
于 2008-08-30T21:31:28.517 に答える
1

1 つのオプションは、別の配列にラップすることです。

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

ちょっと醜いですが、各アイテムは配列であるため、キャストして問題を解決することはできません... Foo(params object items) の場合のように、次のようにすることができます。

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

または、配列を 1 つだけ取る 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 });
}
于 2008-08-30T21:31:49.343 に答える
1
new[] { (object) 0, (object) null, (object) false }
于 2012-06-21T23:37:02.490 に答える