13

このコレクション プロパティを別のものに置き換える必要があるため、クラスのコレクション プロパティに Obsolete のフラグを立てて、すべての出現箇所を見つけ、警告リストに修正すべきものの縮小リストを保持しようとしました。


編集: Microsoft Connect を通じてこれを送信しました。問題番号 417159です。

編集 16.11.2010 : .NET 3.5 および 4.0 用にコンパイルする場合の両方で、これが C# 4.0 コンパイラで機能することを確認しました。投稿されたコードに、「Not OK?」というコメントを含む 4 つの警告が表示されます。


しかし、驚いたことに、リストにはいくつかの出現しか含まれていませんでした。私が知っていたよりもはるかに少なく、spotchecks は、何らかの理由で、警告リストでコンパイラによってプロパティの使用が常に廃止されているとフラグ付けされていないことを示しています。 .

Visual Studio 2008 でコンパイルできるサンプル プログラムを次に示します。

これらのうち、#1 から #4 でタグ付けされた末尾近くの 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
        }
    }
}
4

3 に答える 3

18

これは本物のバグです。残念ながら、このケースを見逃したリファクタリングのクリーンアップが原因です。VS 2010/NDP 4.0 で予定されている C# 4.0 コンパイラ リリース用にこれを修正しましたが、現在 Orcas で修正する予定はなく、残念ながらこれに対処するための回避策はありません。

言いたくないのですが、この問題を修正するには、NDP 4 csc.exe または VS2010 が利用可能になったときにアップグレードする必要があります。

これについて、私の新鮮な新しい msdn ブログにエントリを投稿することを考えています。リファクタリングによってコードが破損する可能性があることを示す良い事例です。

イアン・ハリデー

C# コンパイラ SDE
マイクロソフト

于 2009-03-17T02:20:16.967 に答える
14

うーん...私にはコンパイラのバグのように見えます! 以下に失敗します (ECMA 334v4):

24.4.3 Obsolete 属性 Obsolete 属性は、使用されなくなった型および型のメンバーをマークするために使用されます。Obsolete 属性で装飾された型またはメンバーをプログラムが使用する場合、コンパイラは開発者に警告するために警告またはエラーを発行し、問題のあるコードを修正できるようにします。具体的には、エラー パラメータが指定されていない場合、またはエラー パラメータが指定されていて値が false の場合、コンパイラは警告を発行します。error パラメータが指定され、値が true の場合、コンパイラはコンパイル時エラーを発行します。

特に、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();}
    }
}

MS C# 2.0 コンパイラと同様に、mono 2.0 はそれを正しく行うことに注意してください。壊れているのは MS C# 3.0 (.NET 3.5) コンパイラだけです。

于 2009-02-23T10:26:25.690 に答える
4

Marc に同意します。これはコンパイラのバグのようです。興味深いことに、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)
于 2009-02-23T10:32:11.323 に答える