【问题标题】:Why does this code compile without error even though the class is marked Obsoleted?为什么即使该类标记为“已过时”,此代码也可以无错误地编译?
【发布时间】:2011-08-22 19:35:52
【问题描述】:

这是 Visual Studio 2008。显然与扩展的静态类有关。

public class Dummy
{
    public readonly int x;

    public Dummy(int x)
    {
        this.x = x;
    }

    public override string ToString()
    {
        return x.ToString();
    }
}

[Obsolete("Do Not Use", true)]
public static class Extensions
{
    public static int Squared(this Dummy Dummy)
    {
        return Dummy.x * Dummy.x;
    }
}

class Program
{
    static void Main(string[] args)
    {
        var d = new Dummy(42);
        Console.WriteLine(String.Format("{0}^2={1}", d, d.Squared()));
    }
}

【问题讨论】:

    标签: c# .net visual-studio-2008 attributes obsolete


    【解决方案1】:

    调用过时的函数是警告,而不是错误,除非您将编译器设置更改为也停止警告 - 使警告表现得像错误。

    除非我的代码中存在其他“真实”错误,否则我通常不会看到这些警告。

    另请注意,在您的特定情况下,您将类标记为过时 - 而不是方法。这可能很重要。

    【讨论】:

    • Obsolete属性的第二个参数表示是否应该是错误。
    【解决方案2】:

    我认为您需要将属性放在 Squared 上,而不是类上。

    【讨论】:

    • 没有。它定义了AttributeUsage.Class
    • 在非静态类上,可以将一个类标记为过时,而无需将其他任何东西标记为过时。我知道静态类根本不像非静态类,但它没有给出任何警告表明该属性在该级别无效,这似乎很奇怪。
    • 对静态类有效,将任何非扩展函数放入其中并尝试调用它会抛出错误。扩展函数只是避开了静态类上的属性的通知,因为它实际上并不是 Extensions 类的一部分,而是它的 Dummy 类的一部分。
    • @Felan,在 Ryan 的回答和 Aliostad 的示例中,如果显式访问它,有时它似乎可以被视为该过时类的一部分。所以这是一种精神分裂症。
    【解决方案3】:

    因为它是一个扩展方法,你不是直接访问静态类,编译器会生成那个代码。

    相反,如果您显式访问 Squared 方法,则会收到编译时错误。

    Extensions.Squared(d)
    

    由于这是一个扩展方法,但是,您只是隐式调用该方法,因此需要将属性应用于方法本身。

    public static class Extensions
    {
        [Obsolete("Do Not Use", true)]
        public static int Squared(this Dummy Dummy)
        {
            return Dummy.x * Dummy.x;
        }
    }
    

    另一方面,完全删除(或重命名)该类将达到相同的目的 - 在这种情况下,您肯定会遇到编译时错误。 :)

    编辑
    您可以向 Microsoft here 提交错误报告。这似乎是应该由编译器处理的行为。

    【讨论】:

    • 这并不是说如果编译器支持扩展方法的静态类上的Obsolete 属性就不好了。
    • 这有点吓人,因为您可能认为可以删除标记为 Obsolete/True 的内容(可能还必须删除未使用的代码路径中的其他 Obsolete/True 内容,我猜这可能被认为是一个微妙的变化)。
    • 你当然可以有一个标记为 obsolete/true 的非静态类,它依赖于它有其他过时/true 的东西,只要对象模型的整个部分是孤立的,它就会编译而不会出错。
    【解决方案4】:

    我认为你发现了一个编译器错误

    虽然扩展方法会被编译成静态方法用法,但是编译器似乎没有检查它因为在编译时它以实例方法调用的格式存在


    原因就在这里。如果我声明第二种方法:

    [Obsolete("Do Not Use", true)]
    public static class Extensions
    {
        public static int Squared(this Dummy Dummy)
        {
            return Dummy.x * Dummy.x;
        }
    
        public static int Squared2(Dummy Dummy)
        {
            return Dummy.x * Dummy.x;
        }
    
    }
    

    现在它在第三行而不是第二行抱怨:

    class Program
    {
        static void Main(string[] args)
        {
            var d = new Dummy(42);
            Console.WriteLine(String.Format("{0}^2={1}", d, d.Squared())); // Fine!?
            Console.WriteLine(String.Format("{0}^2={1}", d, Extensions.Squared2(d))); // COmplains as expected
        }
    }
    

    【讨论】:

      【解决方案5】:

      在 VS2010 中也是如此。看起来像一个错误。我会把它输入数据库。

      您可以通过将属性放在实际方法上来解决该错误。

      感谢您的报告!

      【讨论】:

        猜你喜欢
        • 2019-04-18
        • 2012-01-03
        • 1970-01-01
        • 1970-01-01
        • 2018-12-06
        • 1970-01-01
        • 1970-01-01
        • 2016-02-01
        • 1970-01-01
        相关资源
        最近更新 更多