21

暗黙的に型指定された変数で配列初期化子を使用できないのはなぜですか?

string[] words = { "apple", "strawberry", "grape" };                 // legal
string[] words = new string[]{ "apple", "strawberry", "grape" };     // legal
var words = new []{ "apple", "strawberry", "grape" };                // legal
var words = new string[]{ "apple", "strawberry", "grape" };          // legal

var words = { "apple", "strawberry", "grape", "peach" };             // ILLEGAL

この制限の技術的な理由はありますか?次のようにタイプを推測できないのはなぜですか。

var number = 10;
var text = "Hello";

コンパイラは私が何をしようとしているのかを明確に知っていますが、それは許可されません。

CS0820:暗黙的に型指定されたローカルに配列初期化子を割り当てることができません


更新:4つの有効な配列宣言メソッドを使用してプログラムをコンパイルしましたが、同じILが生成されます:http://pastebin.com/28JDAFbL

これは私の混乱を増すだけです。そして、「仕様がそう言っているので、それはこのようなものです」はほとんど役に立ちません。なぜこのようなスペックなのですか?ここでの理論的根拠は何ですか?

4

3 に答える 3

35

暗黙的に型指定された変数で配列初期化子を使用できないのはなぜですか? なんでこんな仕様に?ここでの根拠は何ですか?

この決定が下されたとき、私はデザイン チームにいなかったので、デザイン ノート (*) はこの件について沈黙しています。しかし、この決定が下された 2005 年にその部屋にいた人に聞いてみました。

説明は平凡です。設計チームは、そもそも配列初期化子の構文にあまり満足していませんでした。率直に言って、配列初期化子が式ではなく、構文的にローカル宣言またはフィールド宣言でしか使用できないのは、まったく奇妙です。これはパーサーを複雑にします。奇妙に思える

int[] x = {1};

合法のはずですが、

M({1});

ではありません。

配列の初期化構文は、編集時のコード分析中のエラー回復も複雑にします。次のようなものがあるとします。

class C
{
    void M()
    {
        {
            int result = whatever();
            ...
        }
        {
            int result = somethingElse();
            ...
        }
    }
}

そして、エディターで新しい宣言の入力を開始します。

    void M()
    {
        int[] x = 
        {
            int result = whatever();

そして突然、パーサーは、「null;」と入力しようとしている貧しいユーザーを混乱させない方法で状況を明確にする必要があります。明らかに、コードのブロックでローカル変数を初期化するつもりはありませんが、パーサーは、ここでブレースが合法的に配列初期化子の一部になることしかできないと言う権利を完全に持っています。したがって、それは「int結果」です予想外です。

つまり、簡単に言えば、「古典的な」配列初期化子はちょっとした機能の誤りです。後方互換性のため、それらを取り除くことはできません。しかし、より多くの場所で使用できるようにすることで、それらの使用を奨励したくもありません。

設計チームは、配列初期化子の前に「new[]」を追加し、それを有効な式にするというアイデアを思いつきました。これで問題は解決しました。古典的な配列初期化子の誤機能が言語の新しい領域に「忍び寄る」ことはなく、「ここで新しい配列を作成している」ことを明確に示す簡潔だが読みやすい構文があります。

この話の教訓は、構文は永遠に続くものなので、最初から正しく理解するように努めることです。


(*) 私の検索では、いくつかの興味深いことがわかりました。チームは当初、「var」はこの機能に選択されたキーワードではないだろうと考えていました。どうやらそれは彼らに成長しました。また、ある設計では、「var」ローカルを暗黙的に型指定するだけでなく、init-once ローカルにする必要がありました。明らかに、init-once ローカルを実装したことはありません。

于 2011-09-08T20:33:38.870 に答える
8

これを行うには、次の構文を使用できます。

var words = new[] { "apple", "strawberry", "grape", "peach" };
于 2011-09-08T16:34:54.673 に答える
5

おそらく、タイプを指定していないためです。配列、リスト、またはその他のコレクションです。

ただし、これは機能し、同じように見え、数文字長くなります。

var words = new[]{ "apple", "strawberry", "grape", "peach" };   
于 2011-09-08T16:36:10.613 に答える