C# のコレクション プロパティのプロパティを呼び出すときに、それらのプロパティに廃止のフラグが立てられないのはなぜですか?
-
05-09-2019 - |
質問
このコレクション プロパティを別のものに置き換える必要があるため、すべての発生箇所を検索し、修正すべきものの縮小リストを警告リストに保持するために、クラスのコレクション プロパティに廃止のフラグを立てようとしました。
編集:これは Microsoft Connect 経由で送信しました。 問題 #417159.
編集 2010 年 11 月 16 日:これが、.NET 3.5 および 4.0 用にコンパイルする場合の両方で、C# 4.0 コンパイラで動作することを確認しました。投稿されたコードには、「Not OK?」というコメントを含む 4 つの警告が表示されます。
しかし、驚いたことに、リストには、私が知っていたよりもはるかに少ない数件の出現しか含まれておらず、スポットチェックにより、何らかの理由で、警告リストのコンパイラーによってプロパティの使用法が常に廃止されているとは限らないことがわかりました。 。
これは、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
}
}
}
解決
ふーむ...私にはコンパイラのバグのように思えます。次のことは失敗します (ECMA 334v4)。
24.4.3時代遅れの属性属性は、もはや使用されないタイプのタイプとメンバーをマークするために使用されます。プログラムが時代遅れの属性で装飾されたタイプまたはメンバーを使用する場合、コンパイラは開発者に警告するために警告またはエラーを発行するため、問題のコードを修正できるようにします。具体的には、コンパイラは、エラーパラメーターが提供されていない場合、またはエラーパラメーターが提供され、値がfalseの場合、警告を発行するものとします。エラーパラメーターが指定されており、値が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) コンパイラだけです。
他のヒント
これは本物のバグです。残念ながら、リファクタリングのクリーンアップにより、このケースは見逃されました。VS 2010/NDP 4.0 でリリースされる C# 4.0 コンパイラ用にこの問題を修正しましたが、現時点では Orcas で修正する予定はなく、残念ながら、これに対処する私が知っている回避策はありません。
言いたくないのですが、この問題を解決するには、NDP 4 csc.exe または VS2010 が利用可能になったら、それらにアップグレードする必要があります。
これについては、新しい msdn ブログにエントリを投稿しようと考えています。リファクタリングがどのようにコードを破壊する可能性があるかを示す良い例になります。
イアン・ハリデー
C# コンパイラ SDE
マイクロソフト
私もマルクさんの意見に同意します:コンパイラのバグのようです。興味深いことに、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)