Perché le proprietà della raccolta C # non vengono contrassegnate come obsolete quando si chiamano le proprietà su di esse?

Ho provato a contrassegnare una proprietà della raccolta su una class come Obsoleta per trovare tutte le occorrenze e mantenere un elenco di restringimenti delle cose da correggere nella mia lista di avvisi, a causa del fatto che abbiamo bisogno di sostituire questa proprietà della raccolta con qualcos’altro.


Modifica : l’ho inviato tramite Microsoft Connect, numero 417159 .

Modifica 16.11.2010 : verificato che funzioni ora nel compilatore C # 4.0, sia durante la compilazione per .NET 3.5 e 4.0. Ricevo 4 avvisi nel codice pubblicato, incluso quello con il commento “Non è OK?”.


Tuttavia, con mia sorpresa, la lista conteneva solo alcune apparizioni, molto meno di quanto io sapessi che c’erano, e le tacche mi dicono che per qualche ragione, l’uso della proprietà non è sempre contrassegnato come obsoleto dal compilatore nella lista di avvertimenti .

Ecco un programma di esempio, pronto per la compilazione in Visual Studio 2008.

Nota le quattro righe vicino alla fine contrassegnate con # 1- # 4, di queste, mi aspetterei che tutte riportino che la proprietà utilizzata era obsoleta, ma la # 3 non lo è, e sembra che se passo avanti alle proprietà o ai metodi della raccolta direttamente, l’utilizzo della proprietà stessa non viene contrassegnato come obsoleto. Nota che il n. 3 e il n. 4 fanno riferimento alla stessa proprietà e il n. 4 è contrassegnato come se utilizzasse una proprietà obsoleta, mentre il n. 3 non lo è. I test mostrano che se, nell’espressione, accedo alle proprietà o ai metodi della raccolta restituiti dalla proprietà, il compilatore non si lamenta.

È un bug o è una “gem nascosta” del compilatore C # di cui non ero a conoscenza?

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 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 ValueList { get { return new List(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 list = bc.ValueList; // #4 - OK } } } 

Hmm … sembra un bug del compilatore per me! Non riesce (ECMA 334v4):

24.4.3 L’attributo Obsoleto L’attributo Obsoleto viene utilizzato per contrassegnare tipi e membri di tipi che non dovrebbero più essere utilizzati. Se un programma utilizza un tipo o un membro decorato con l’attributo Obsoleta, il compilatore deve emettere un avviso o un errore per avvisare lo sviluppatore, in modo che il codice incriminato possa essere corretto. Nello specifico, il compilatore deve emettere un avviso se non viene fornito alcun parametro di errore o se viene fornito il parametro di errore e il valore è falso. Il compilatore deve emettere un errore in fase di compilazione se il parametro di errore è specificato e ha il valore true.

In particolare, se contrassegnato come vero, dovrebbe emettere un errore e non lo è. Buona scoperta! Puoi segnalarlo su “connect”, o se non vuoi il dolore di creare un login, fammelo sapere e lo registrerò felicemente (riferendosi al tuo post qui, nessun tentativo di “rubare” nulla).

(aggiornare)

Codice ridotto da riprodurre:

 using System; using System.Collections.Generic; static class Program { static void Main() { int count = Test.Count; } [Obsolete("Should error", true)] public static List Test { get {throw new NotImplementedException();} } } 

Si noti che il 2.0 mono funziona correttamente, così come il compilatore MS C # 2.0. È solo il compilatore MS C # 3.0 (.NET 3.5) che è danneggiato.

Questo è un bug reale. Sfortunatamente a causa di una pulizia del refactoring che ha mancato questo caso. Ho risolto questo problema per il rilascio del compilatore C # 4.0 in arrivo su VS 2010 / NDP 4.0 ma non ci sono piani per risolverlo ora in Orcas e sfortunatamente non c’è alcun lavoro in giro che io sappia trattare con questo.

Odio dirlo, ma dovrai aggiornare l’NDP 4 csc.exe o VS2010 quando saranno disponibili per risolvere questo problema.

Sto pensando di pubblicare una voce sul mio nuovo blog msdn su questo. Fa un buon esempio aneddotico di come il refactoring può infrangere il tuo codice.

Ian Halliday

Compilatore C # SDE
Microsoft

Sono d’accordo con Marc: sembra un bug del compilatore. È interessante notare che gmcs (il compilatore Mono C #) ha ragione:

 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)