2010-12-20 54 views
0

我遇到了一些無法預料的移植到mono 2.8.1的後果。問題可以被歸結爲一個示例程序(I一直無法進一步降低它,切割幾個類和〜1000行的代碼下面引用該文件之後)單聲道+命名/可選參數=編譯器錯誤?

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"); 
    } 
} 

編譯的上面的代碼與MCS給出輸出:

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 

取出使用可選/命名參數(即調用新的Person(1.0,空, 「李四」)或新的Person(1.0,空,名稱: 「李四」),或新的Person( 1.0,「John Doe」))導致了完美的編譯。此外,在VS2010下,文件(以及我開始的整個解決方案)編譯得很好。 Casting會移除錯誤CS0266,但不會移除CS0584 - 因此在那裏不會感到意外。我的問題:是我做錯了什麼,或者mcs(即mcs中的bug對我來說很明顯 - 還有什麼,內部錯誤會是什麼意思,但也許沒關係,這樣的程序不會編譯),或者也許在VS2010中的微軟編譯器不應該讓這樣的代碼編譯?

我敢打賭,這是MCS誰的錯(不能猜對構造函數),但也許它,否則,我不應該知道的?

PS。我嘗試在Google和Novell的Bugzilla中搜索這樣一個已知的bug,但無法找到任何相關的東西。再一次,我可能會失明;)

+0

你甚至可以設置一個字符串爲空... – Blam 2010-12-20 23:55:23

+0

有沒有錯誤編譯使用visual studio。我沒有單聲道來嘗試它,以確認。 – 2010-12-21 00:05:54

+0

@Courtney:單聲道可在線獲取[此處](http://ideone.com/kZ2Eo)。 – Vlad 2010-12-21 00:07:11

回答

3

好的,這裏有。事故的確是由於第三次超載,Person(double income, int age, string name = null)。 編譯器認爲您正在嘗試傳遞比簽名中列出的參數少的參數,因此它會查找可選參數。它高興地注意到name是可選的,並假定你沒有通過這個參數。它通過在所提供參數的末尾添加一個佔位符來完成此操作。接下來,它會重新排列列表中的命名參數,以便它們以正確的位置結束。這意味着John Doe現在正確地位於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

你的答案是否也適用於mono-2.8.1?我不知道你是否知道它的確如此,並默默地假設或者你錯過了我使用2.8.1的事實? AFAIR 2.6.7完全支持命名/可選參數,但我不知道代碼本身是否改變... – triazotan 2010-12-21 01:48:55

+0

不知道。由於兩個版本都出現同樣的崩潰,我認爲這也適用於2.8.1。但是,我在這裏只有2.6.7,所以我無法測試。 – Jester 2010-12-21 01:56:10

0

對於其他人來此線程。該錯誤仍然存​​在於截至2013年4月的最新版本的Mono Compiler中。我創建了一個解決方案,無需使用C#重載函數修改編譯器。

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

Foo(int a, bool b, string c)