2009-02-23 44 views
13

我試圖將一個類的集合屬性標記爲Obsolete,以查找所有發生的事件,並在我的警告列表中保留一個縮小的事件列表以解決問題,因爲我們需要用其他事件替換此集合屬性。爲什麼C#集合屬性在調用屬性時沒有被標記爲廢棄?


編輯:我已經通過Microsoft連接,issue #417159提交此。

編輯16.11.2010:已驗證此功能現在可在C#4.0編譯器中使用,無論是在編譯.NET 3.5還是4.0時。在發佈的代碼中,我收到4條警告,其中包括評論爲「不行?」的警告。


然而,出乎我的意料,列表僅包含幾個occurances,遠遠低於我知道有,並且spotchecks告訴我,由於某種原因,財產的用途並不總是標記爲過時由編譯器在警告列表中。

下面是一個例子程序,準備在Visual Studio編譯2008年

注意接近尾聲標有#1-#4,這些四大行,我希望所有的人都向大家報告,使用的屬性已過時,但#3不是,似乎如果直接轉到集合屬性或方法,屬性本身的使用不會被標記爲過時。請注意,#3和#4引用相同的屬性,#4被標記爲使用廢棄的屬性,而#3不是。測試表明,如果在表達式中,我訪問該屬性返回的集合的屬性或方法,編譯器不會發出抱怨。

這是一個錯誤,或者這是一個「隱藏的寶石」的C#編譯器,我不知道?

using System; 
using System.Collections.Generic; 

namespace TestApp 
{ 
    public abstract class BaseClass 
    { 
     [Obsolete] 
     public abstract String Value 
     { 
      get; 
     } 

     [Obsolete] 
     public abstract String[] ValueArray 
     { 
      get; 
     } 

     [Obsolete] 
     public abstract List<String> ValueList 
     { 
      get; 
     } 
    } 

    public class DerivedClass : BaseClass 
    { 
     [Obsolete] 
     public override String Value 
     { 
      get 
      { 
       return "Test"; 
      } 
     } 

     [Obsolete] 
     public override String[] ValueArray 
     { 
      get 
      { 
       return new[] { "A", "B" }; 
      } 
     } 

     [Obsolete] 
     public override List<String> ValueList 
     { 
      get 
      { 
       return new List<String>(new[] { "A", "B" }); 
      } 
     } 
    } 

    public class Program 
    { 
     public static void Main(String[] args) 
     { 
      BaseClass bc = new DerivedClass(); 
      Console.Out.WriteLine(bc.Value);    // #1 - OK 
      Console.Out.WriteLine(bc.ValueArray.Length); // #2 - OK 
      Console.Out.WriteLine(bc.ValueList.Count); // #3 - Not OK? 
      List<String> list = bc.ValueList;   // #4 - OK 
     } 
    } 
} 
+0

我打上你的「連接」的驗證,並給它一個評價? – 2009-02-23 10:40:18

+0

順便說一句,我也沒有預料到前一個修復C#4.0 ;代碼將在2.0中編譯?也許試試2.0編譯器... – 2009-02-23 10:46:30

+0

不,我們會做,我只是偶然發現這一點,當試圖使用ObsoleteAttribute作爲一個快速的方式來獲得一個「todo」列表的東西來解決之前,我們繼續前進重構。 – 2009-02-23 10:53:46

回答

14

嗯......看起來像一個編譯器bug給我!它失敗以下(ECMA 334v4):

24.4.3過時屬性過時屬性用於標記 類型和應 不再被使用的類型的成員。如果某個程序使用 類型或用 廢棄屬性修飾的成員,則編譯器應發出警告或 錯誤,以提醒開發人員 ,以便修復有問題的代碼。 具體來說,如果沒有提供錯誤參數 ,或者錯誤參數爲 並且值爲false,則編譯器應發出 警告。如果指定的錯誤參數爲 並且值爲true,則編譯器將發出編譯時間 錯誤。

特別是,當標記爲真時,它應該發出錯誤,而不是。好找!你可以在「連接」上報告它,或者如果你不想設置登錄的痛苦,讓我知道,我會很樂意記錄它(在這裏引用你的帖子;不要試圖「偷」任何東西)。

(更新)

精簡碼重現:

using System; 
using System.Collections.Generic; 
static class Program { 
    static void Main() { 
     int count = Test.Count; 
    } 

    [Obsolete("Should error", true)] 
    public static List<string> Test { 
     get {throw new NotImplementedException();} 
    } 
} 

注意,單聲道2.0得到它的權利,一樣的MS C#2.0的編譯器。它只是MS C#3.0(.NET 3.5)編譯器被破壞。

+0

好的,很好,這證實了我的懷疑,我編輯了我的問題併發布了連接問題的鏈接。 – 2009-02-23 10:37:55

4

我同意馬克:它看起來像一個編譯器錯誤。有趣的是,gmcs(Mono C#編譯器)正確:

Test.cs(65,26): warning CS0219: The variable `list' is assigned but its value is never used 
Test.cs(62,38): warning CS0612: `TestApp.BaseClass.Value' is obsolete 
Test.cs(63,38): warning CS0612: `TestApp.BaseClass.ValueArray' is obsolete 
Test.cs(64,38): warning CS0612: `TestApp.BaseClass.ValueList' is obsolete 
Test.cs(65,36): warning CS0612: `TestApp.BaseClass.ValueList' is obsolete 
Compilation succeeded - 5 warning(s) 
18

這是一個真正的bug。不幸的是,由於重構清理錯過了這種情況。我已經解決了VS 2010/NDP 4.0中的C#4.0編譯器版本問題,但目前還沒有計劃在Orcas中修復它,不幸的是我沒有辦法解決這個問題。

我討厭這麼說,但是當它們可用於解決此問題時,您需要升級到NDP 4 csc.exe或VS2010。

我正在考慮在我的全新msdn博客上發佈關於此的條目。做了一個很好的軼事例子,說明重構如何破壞你的代碼。

伊恩·哈利迪

C#編譯器SDE
微軟

相關問題