为什么在调用 C# 集合属性的属性时,它们没有被标记为过时?

发布于 2024-07-13 23:44:13 字数 2233 浏览 15 评论 0原文

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


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

编辑 16.11.2010:已验证此功能现在可以在 C# 4.0 编译器中运行,无论是针对 .NET 3.5 还是 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
        }
    }
}

I tried to flag a collection property on a class as Obsolete to find all the occurances and keep a shrinking list of things to fix in my warning-list, due to the fact that we need to replace this collection property with something else.


Edit: I've submitted this through Microsoft Connect, issue #417159.

Edit 16.11.2010: Verified that this now works in the C# 4.0 compiler, both when compiling for .NET 3.5 and 4.0. I get 4 warnings in the posted code, including the one with the comment "Not OK?".


However, to my surprise, the list only contained a few occurances, far fewer than I knew there were, and spotchecks tells me that for some reason, the usage of the property isn't always flagged as obsolete by the compiler in the warning list.

Here's an example program, ready to compile in Visual Studio 2008.

Note the four lines near the end tagged with #1-#4, of these, I'd expect all of them to report that the property used was obsolete, but #3 isn't, and it seems that if I just move on to the collection properties or methods directly, the usage of the property itself isn't flagged as obsolete. Note that #3 and #4 is referencing the same property, and #4 is flagged as using an obsolete property, whereas #3 isn't. Tests shows that if, in the expression, I access properties or methods of the collection the property returns, the compiler doesn't complain.

Is this a bug, or is this a "hidden gem" of the C# compiler I wasn't aware of?

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

ま昔日黯然 2024-07-20 23:44:13

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

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

我正在考虑在我的新 msdn 博客上发布关于此的条目。 这是一个很好的轶事例子,说明重构如何破坏您的代码。

Ian Halliday

C# 编译器 SDE
微软

This is a genuine bug. Unfortunately due to a refactoring clean up that missed this case. I fixed this for the C# 4.0 compiler release coming up in VS 2010/NDP 4.0 but there are no plans to fix it now in Orcas and unfortunately there is no work around I know of to deal with this.

I hate to say it but you will need to upgrade to the NDP 4 csc.exe or VS2010 when they become available to fix this issue.

I'm thinking about posting an entry on my fresh new msdn blog about this. Makes a good anecdotal example of how refactoring can break your code.

Ian Halliday

C# Compiler SDE
Microsoft

千と千尋 2024-07-20 23:44:13

嗯...对我来说看起来像是一个编译器错误! 它无法满足以下条件 (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) 编译器被破坏。

Hmm... looks like a compiler bug to me! It fails the following (ECMA 334v4):

24.4.3 The Obsolete attribute The attribute Obsolete is used to mark
types and members of types that should
no longer be used. If a program uses a
type or member that is decorated with
the Obsolete attribute, then the
compiler shall issue a warning or
error in order to alert the developer,
so the offending code can be fixed.
Specifically, the compiler shall issue
a warning if no error parameter is
provided, or if the error parameter is
provided and has the value false. The
compiler shall issue a compile-time
error if the error parameter is
specified and has the value true.

In particular, when marked true it should issue an error, and it doesn't. Good find! You could report it on "connect", or if you don't want the pain of setting up a login, let me know and I'll happily log it (referencing your post here; no attempt to "steal" anything).

(update)

Reduced code to reproduce:

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

Note that mono 2.0 gets it right, as does the MS C# 2.0 compiler. It is only the MS C# 3.0 (.NET 3.5) compiler that is broken.

美人骨 2024-07-20 23:44:13

我同意马克的观点:它看起来像是一个编译器错误。 有趣的是,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)

I agree with Marc: it looks like a compiler bug. Interestingly, gmcs (the Mono C# compiler) gets it right:

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)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文