web-dev-qa-db-ja.com

パラメータIEnumerable <T> c#

なぜ、paramsでIEnumerableを使用できないのですか?これは修正されますか?ジェネリックを使用するように古いライブラリを書き直してもらいたい...

60
Dested

なぜ、paramsでIEnumerableを使用できないのですか?

この質問は、設計チームが言語に機能をしない理由を提供する必要があることを前提としています。この前提は誤りです。

むしろ、ユーザーが機能を使用するには、その機能を検討、設計、指定、実装、テスト、文書化、および出荷する必要があります。これらはすべてコストがかかります。

「params enumerable」機能は考えられ、設計されました。仕様化、実装、テスト、文書化、出荷はされていません。

したがって、この機能は使用できません。


更新:これを書いている時点(2015年初頭)は現在指定されていますが、実装、テスト、文書化、および出荷は、C#6.0で2014年の後半にカットされました。ここでLucianの発表を参照してください: http:// roslyn.codeplex.com/discussions/56882

まだ実装、テスト、文書化、出荷されていないため、そのような機能はまだありません。うまくいけば、これがC#の仮想的な将来のバージョンになることを願っています。


更新:「機能」とは私たちの頭の中でさまざまなアイデアがある可能性があるため、「機能」の意味を明確にする必要があります。私が話している機能は、あなたが次のようなことを言えるようにすることです

void Frob(params IEnumerable<int> x)
{
    foreach(int y in x) ...
}

呼び出しサイトは、整数のシーケンスを渡す「通常の形式」、またはFrob(10、20、30)の「拡張形式」のいずれかになります。展開された形式の場合、コンパイラは、Frob(new int [] {10、20、30})と同じように呼び出しを生成します。これは、param配列の場合と同じです。この機能のポイントは、メソッドが配列へのランダムアクセスを使用しないことがよくあることです。そのため、paramsが配列であるという要件を緩和できます。代わりに、paramsをシーケンスにすることもできます。

オーバーロードを作成することで、今日これを行うことができます。

void Frob(params int[] x) { Frob((IEnumerable<int>)x); }

void Frob(IEnumerable<int> x)
{
    foreach(int y in x) ...
}

これは少し苦痛です。単純に、params引数のタイプとしてIEnumerableを使用して、それを使用できるようにすることができます。

これは修正されますか?

そうだといい。この機能は長い間リストに載っています。これにより、多くの関数がLINQでより適切に機能するようになります。

Frob(from c in customers select c.Age);

frobの2つの異なるバージョンを作成する必要はありません。

ただし、これは単なる「小さな利便性」機能です。それは実際に言語に新しい力の多くを追加するわけではありません。それが、「仕様が書かれている」段階に到達するために、優先度リストでそれを十分に高くしなかった理由です。

ジェネリックを使用するように古いライブラリを書き換えてもらいたいです。

コメントに注意。

92
Eric Lippert

ああ、私はmayがあなたの意味を理解したと思います。次のようなメソッドを宣言できるようにしたいと思います。

public void Foo<T>(params IEnumerable<T> items)
{
}

そして、次のような「通常の」引数でそれを呼び出すことができます。

IEnumerable<string> existingEnumerable = ...;
Foo(existingEnumerable);

または、次のような複数のパラメータを使用します。

Foo("first", "second", "third");

それはあなたが求めているものですか? (最初のフォームでは、単一の要素を持つT=stringではなくT=IEnumerable<string>を使用することに注意してください...)

もしそうなら、私はそれに同意します可能性があります有用です-しかし、それは十分に簡単です:

public void Foo<T>(params T[] items)
{
    Foo((IEnumerable<T>) items);
}

public void Foo<T>(IEnumerable<T> items)
{
}

上記を特に醜い回避策にするのに十分な頻度でこれを行っているとは思いません。

上記のコードを呼び出すときは、コンパイラがparamsの例を優​​先しないように、型引数をexplicitlyに指定する必要があることに注意してください。だから例えば:

List<string> x = new List<string>();
Foo<string>(x);
12
Jon Skeet

Paramsパラメータは配列として送信され、IEnumerable<T>は、配列として機能するために必要なランダムアクセスを提供しません。

メソッドを呼び出すときに、IEnumerableから配列を作成する必要があります。

TheMethod(theIEnumerable.ToArray());
4
Guffa