13

我试图将类上的集合属性标记为已过时,以查找所有出现的情况并在我的警告列表中保留要修复的缩小列表,因为我们需要用其他东西替换这个集合属性。


编辑:我已经通过 Microsoft Connect 提交了这个,问题 #417159

编辑 16.11.2010:验证现在在为 .NET 3.5 和 4.0 编译时,这在 C# 4.0 编译器中有效。我在发布的代码中收到 4 条警告,包括带有注释“不好?”的一条。


然而,令我惊讶的是,该列表仅包含一些事件,远远少于我所知道的,并且抽查告诉我,出于某种原因,该属性的使用并不总是被编译器在警告列表中标记为过时.

这是一个示例程序,可以在 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
        }
    }
}
4

3 回答 3

18

这是一个真正的错误。不幸的是,由于错过了这种情况的重构清理。我为 VS 2010/NDP 4.0 中即将发布的 C# 4.0 编译器版本修复了这个问题,但现在没有计划在 Orcas 中修复它,不幸的是,我知道没有解决这个问题的方法。

我不想这么说,但是当 NDP 4 csc.exe 或 VS2010 可用时,您将需要升级到它们来解决此问题。

我正在考虑在我全新的 msdn 博客上发布一个关于此的条目。为重构如何破坏您的代码提供了一个很好的轶事示例。

伊恩·哈利迪

C# 编译器 SDE
Microsoft

于 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();}
    }
}

请注意,mono 2.0 是正确的,MS C# 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 回答