2010-12-20 13 views
0

私はモノ2.8.1に移植すると予想外の結果に遭遇しました。 MCSで上記のコードの問題サンプルプログラムを煮詰めすることができます(私は以下に引用されるファイルにいくつかのクラスと〜コードの1000行をカットした後、さらにそれを軽減することができませんでした)Mono + named/optional parameters =コンパイラのバグ?

public class Person 
{ 
    public Person(int age, string name = null){} 
    public Person(double income, string name = null){} 
    public Person(double income, int age, string name = null){} 
} 

class Program 
{ 
    static void Main() 
    { 
     Person p = new Person(1.0, name: "John Doe"); 
    } 
} 

コンパイル出力を提供します「ジョン・ドウ」)、または新しい人(:名前付き/オプションパラメータ(すなわち呼び出して新しい人(1.0、ヌル、「ジョン・ドウ」)か、新しい人(1.0、ヌル、名前の使用を削除する

test.cs(22,24): error CS0584: Internal compiler error: Internal error 
test.cs(22,20): error CS0266: Cannot implicitly convert type `object' to `NamedParams.Person'. 
An explicit conversion exists (are you missing a cast?) 
Compilation failed: 2 error(s), 0 warnings 

1.0、 "John Doe"))は完璧なコンパイルにつながります。また、VS2010では、ファイル(と私が始めた全体のソリューション)はうまくコンパイルされます。キャスティングでエラーCS0266が削除されますが、CS0584は削除されません。

私の質問:何か間違っている、つまりmcs(すなわちmcsのバグが私には分かります。それ以外に何か内部的なエラーがありますが、そういうプログラムはコンパイルできません)またはVS2010のMicrosoftコンパイラは、コンパイルするようなコードを許可すべきではありませんか?

私はそれが間違っている(正しいコンストラクタを推測することはできません)と思っていますが、おそらくそれはそうではなく、私はよく分かりませんか?

PS。 GoogleとNovellのBugzillaの両方でこのような既知のバグを探してみましたが、関連するものは何も見つかりませんでした。再び、私は目が見えないかもしれません;)

+0

文字列をnullに設定することもできますか... – Blam

+0

Visual Studioを使用してこれをコンパイルする際にエラーが発生していません。私は確かめるためにそこにそれを試してモノを持っていない。 –

+0

@Courtney:Monoはオンラインで入手できます[こちら](http://ideone.com/kZ2Eo)。 – Vlad

答えて

3

さて、ここに行きます。クラッシュは実際には3番目の過負荷、Person(double income, int age, string name = null)に起因します。 コンパイラは、シグネチャにリストされているものより少ない引数を渡そうとしているので、オプションの引数を探します。それはうれしいことにnameがオプションで、あなたがその引数を渡していないことを前提としています。これは、指定された引数の最後にプレースホルダを追加することで行います。次に、リスト内の指定された引数を正しい順序で並べ替えるようになります。つまり、はnameの最後の位置に正しく設定されていますが、プレースホルダはageの位置になります。コンパイラはデフォルト値を書き込もうとしますが、デフォルト値を持たない場所にプレースホルダを見つけることにはショックを受けます。これは、プレースホルダがオプションの引数のために追加されただけで、突然それはもはやオプションではないので、これは起こり得ないと考えています。何をすべきか分からず、例外がスローされます。

--- mono-2.6.7.orig/mcs/mcs/ecore.cs 2009-10-02 12:51:12.000000000 +0200 
+++ mono-2.6.7/mcs/mcs/ecore.cs 2010-12-21 02:26:44.000000000 +0100 
@@ -3803,6 +3803,15 @@ 

           int args_gap = Math.Abs (arg_count - param_count); 
           if (optional_count != 0) { 
+          // readjust for optional arguments passed as named arguments 
+          for (int i = 0; i < arguments.Count; i++) { 
+            NamedArgument na = arguments[i] as NamedArgument; 
+            if (na == null) 
+              continue; 
+            int index = pd.GetParameterIndexByName (na.Name.Value); 
+            if (pd.FixedParameters[index].HasDefaultValue) 
+              optional_count--; 
+          } 
             if (args_gap > optional_count) 
               return int.MaxValue - 10000 + args_gap - optional_count; 
+0

答えはモノ2.8.1にも適用されますか?あなたがそれを知っていて、それを静かに仮定したのか、私が2.8.1を使っているという事実を忘れてしまったのかは分かりません。 AFAIR 2.6.7は名前付き/オプションのパラメータを完全にサポートしていましたが、コード自体が変更されたかどうかはわかりません。 – triazotan

+0

わかりません。両方のバージョンが同じクラッシュを表示するので、これは2.8.1にも当てはまります。しかし、私は2.6.7しか持っていないので、私はテストできません。 – Jester

0

このスレッドに来て他の人のために:(しかし、それは何か他のものなので、無保証を破ること)

次のパッチは、この問題を修正するようです。このバグは2013年4月現在のMono Compilerの最新バージョンにはまだあります。私は、C#のオーバーロードされた関数を使用してコンパイラを変更することなく、回避策を作成しました。

Foo(int a, bool b = true) { 
    Foo(a, b, "Default String"); 
} 

Foo(int a, bool b, string c) 
関連する問題