Почему свойства коллекции C # не помечаются как устаревшие при вызове свойств для них?

StackOverflow https://stackoverflow.com/questions/577132

  •  05-09-2019
  •  | 
  •  

Вопрос

Я попытался пометить свойство коллекции в классе как устаревшее, чтобы найти все вхождения и сохранить сокращающийся список того, что нужно исправить в моем списке предупреждений, в связи с тем, что нам нужно заменить это свойство коллекции чем-то другим.


Редактировать:Я отправил это через Microsoft Connect, выпуск №417159.

Редактировать 16.11.2010:Проверено, что теперь это работает в компиляторе C # 4.0, как при компиляции для .NET 3.5, так и для 4.0.Я получаю 4 предупреждения в опубликованном коде, включая одно с комментарием "Не в порядке?".


Однако, к моему удивлению, список содержал всего несколько случаев, гораздо меньше, чем я знал, и spotchecks сообщает мне, что по какой-то причине использование свойства не всегда помечается компилятором как устаревшее в списке предупреждений.

Вот пример программы, готовой к компиляции в 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
        }
    }
}
Это было полезно?

Решение

Хм...по-моему, похоже на ошибку компилятора!Это приводит к следующему сбою (ECMA 334v4):

24.4.3 Устаревший атрибут Атрибут Устаревший используется для обозначения типов и членов типов, которые не должны больше использоваться.Если программа использует тип или элемент, который украшен атрибутом Устаревший, то компилятор должен выдать предупреждение или ошибку, чтобы предупредить разработчика, таким образом, код-нарушитель может быть исправлен.В частности, компилятор должен выдать предупреждение, если параметр ошибки не указан или если параметр ошибки предоставлен и имеет значение 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).

Другие советы

Это настоящая ошибка.К сожалению, из-за очистки рефакторинга, которая пропустила этот случай.Я исправил это для выпуска компилятора C # 4.0, который выйдет в версии VS 2010 / NDP 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)
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top