12

どうやら、C#はC++と同じように'>>'レクサーのジレンマの影響を受けやすいようです。

このC#コードはかなり有効で、コンパイルして正常に実行されます。

var List = new Dummy("List");
var Nullable = new Dummy("Nullable");
var Guid = new Dummy("Guid");

var x = List<Nullable<Guid>> 10;
var y =  List<Nullable<Guid>> .Equals(10,20);

上記のDummyクラスの'<'および'>>'演算子をオーバーロードする必要があります。

しかし、コンパイラーは、「x」の場合、その意味はList、Nullable、およびGuidローカル変数を使用することであると推測することができます。そして、「y」の場合、突然、それらをよく知られたタイプの名前として扱うことを決定します。

別の例を使用して、もう少し詳細な説明を示します。http: //mihailik.blogspot.co.uk/2012/05/nested-generics-c-can-be-stinky.html

問題は、C#コンパイラが「a <b <c>>」を算術式またはジェネリック型/メソッドにどのように解決するかということです。

確かに、それは成功するまでプログラムのテキストに複数の「行き」を持たせようとはしませんか、それともそうしますか?それには、無制限の先読みが必要であり、非常に複雑でもあります。

4

2 に答える 2

7

C#言語仕様の7.6.4.2項に移動しました。

http://download.microsoft.com/download/0/B/D/0BDA894F-2CCD-4C2C-B5A7-4EB1171962E5/CSharp%20Language%20Specification.htm

simple-name(§7.6.2)とmember-access(§7.6.4)の生成は、表現の文法にあいまいさを生じさせる可能性があります。

..。

トークンのシーケンスを(コンテキスト内で)単純な名前(§7.6.2)、メンバーアクセス(§7.6.4)、またはタイプで終わるポインターメンバーアクセス(§18.5.2)として解析できる場合-argument-list(§4.4.1)、終了トークンの直後のトークンが調べられます。それがの1つである場合

()]}:; 、。?==!= | ^

次に、type-argument-listは、simple-name、member-access、またはpointer-member-accessの一部として保持され、トークンのシーケンスの他の可能な解析はすべて破棄されます。それ以外の場合、トークンのシーケンスの他の可能な解析がない場合でも、type-argument-listはsimple-name、member-access、またはpointer-member-accessの一部とは見なされません。これらのルールは、namespace-or-type-name(§3.8)のtype-argument-listを解析するときに適用されないことに注意してください。

したがって、type-argument-listが含まれている場合、実際にあいまいさが生じる可能性があり、1つのトークンを先読みすることで、それを解決するための安価な方法があります。

'>>'とそれに続くトークンの間にメガバイト相当のコメントがあるかもしれないので、それはまだ束縛されていない先見ですが、少なくともルールは多かれ少なかれ明確です。そして最も重要なのは、投機的な深い構文解析の必要がないことです。

于 2012-05-16T19:12:59.187 に答える
-2

編集:あいまいさはないと主張します: あなたの例では、あいまいさはまったくありません。これは、として評価することはできませんList<Guid?>。コンテキスト(追加の10)は、コンパイラーにそれを解釈する方法を示します。

var x = List<Nullable<Guid>> 10;

コンパイラはこれをコンパイルしますか?:

var x = List<Guid?> 10;

そうでないことは明らかです。だから私はまだ曖昧さを探しています。

OTOH、2番目の式:

var y =  List<Nullable<Guid>> .Equals(10,20);

List<Guid?>メソッドを呼び出しているため、として評価する必要があります.Equals。繰り返しますが、これは他の方法で解釈できます。

パラドックスはまったくありません。コンパイラはそれを完全に解析します。私はまだアプラドックスが何であるか疑問に思っています。

あなたは大きな間違いを犯しています。コンパイラーは式全体を解釈し、言語文法を使用してそれらを理解します。式の残りの部分を考慮せずに、あなたが行っているようにコードの断片を調べません。

これらの式は、C#文法に従って解析されます。そして、文法はコードを正しく解釈するのに十分明確です。つまり

var x = List<Nullable<Guid>> 10;

10がリテラルであることは明らかです。文法をフォローアップすると、次のことがわかります。10は*リテラルであるため、* primary-no-array-creation-expressionであり* primary-expressionであり、* unary-expressionであり、 *乗法式。これは*加法式です。* >>の右側で加法式を探す場合、それは*シフト式である必要があることがわかります。したがって、* >>の左側は*加法式として解釈される必要があります。

文法を使用する別の方法を見つけて、同じ式で別の結果を得ることができた場合、私はあなたに同意する必要がありますが、私は同意しません!

ついに:

  • 人間にとって非常に混乱します
  • コンパイラにとって完全に明確で明確です

なぜなら:

  • 私たち人間は、私たちに馴染みのあるテキスト全体の断片を取りながらパターンを識別し、私たちがList<Nullable<Guid>>望むようにそれらを解釈します
  • コンパイラは、のようなおなじみのフラグメントを使用して、私たちのようにコードを解釈しませんList<Nullable<Guid>>。彼らは表現全体を取り、それを言語文法に一致させます。
于 2012-05-16T01:20:17.147 に答える