【问题标题】:Why are C# collection-properties not flagged as obsolete when calling properties on them?为什么 C# 集合属性在调用它们的属性时没有被标记为过时?
【发布时间】:2010-10-09 07:03:01
【问题描述】:

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


编辑:我已通过 Microsoft Connect 提交此内容,issue #417159

Edit 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
        }
    }
}

【问题讨论】:

  • 我已将您的“连接”标记为已验证并给它评分...
  • 顺便说一句,我预计不会在 C# 4.0 之前修复;代码会在 2.0 中编译吗?也许试试 2.0 编译器...
  • 不,我们会做的,我只是在尝试使用 ObsoleteAttribute 作为获取“待办事项”列表的快速方法时偶然发现的,以便在我们继续重构之前修复要修复的事情.

标签: c# properties obsolete


【解决方案1】:

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

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

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

伊恩·哈利戴

C# 编译器 SDE
微软

【讨论】:

  • 感谢您抽出宝贵时间在此处发布。赞赏。
  • 确实如此。我认为 Stack Overflow 的另一个里程碑:)
【解决方案2】:

嗯...在我看来就像一个编译器错误!它失败了以下(ECMA 334v4):

24.4.3 Obsolete 属性 Obsolete 属性用于标记 类型和类型的成员应该 不再使用。如果一个程序使用 装饰有的类型或成员 过时的属性,然后 编译器应发出警告或 错误以提醒开发人员, 所以可以修复有问题的代码。 具体来说,编译器应发出 如果没有错误参数,则发出警告 提供,或者如果错误参数是 提供并且值为 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();}
    }
}

请注意,mono 2.0 是正确的,MS C# 2.0 编译器也是如此。损坏的只是 MS C# 3.0 (.NET 3.5) 编译器。

【讨论】:

  • 好的,很好,这证实了我的怀疑,我已经编辑了我的问题并发布了连接问题的链接。
【解决方案3】:

我同意 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)

【讨论】:

  • 只能接受一个,所以我先接受 Marc 的 :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-07-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多