Почему C # collection-properties не помечаются как устаревшие при вызове свойств для них? - PullRequest
13 голосов
/ 23 февраля 2009

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


Редактировать : я отправил это через 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
        }
    }
}

Ответы [ 3 ]

18 голосов
/ 17 марта 2009

Это настоящая ошибка. К сожалению из-за очистки рефакторинга, который пропустил этот случай Я исправил это в выпуске компилятора C # 4.0, выходящем в VS 2010 / NDP 4.0, но в Orcas сейчас нет планов по его исправлению, и, к сожалению, я не знаю, как с этим справиться.

Мне неприятно это говорить, но вам нужно будет перейти на NDP 4 csc.exe или VS2010, когда они появятся, чтобы решить эту проблему.

Я подумываю о публикации в моем новом новом блоге msdn об этом. Делает хороший пример того, как рефакторинг может сломать ваш код.

Ян Хэллидей

C # Компилятор SDE
Microsoft

14 голосов
/ 23 февраля 2009

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

24.4.3 Атрибут Устаревший Атрибут Устаревший используется для пометки типы и члены типов, которые должны больше не будет использоваться. Если программа использует тип или член, который украшен Устаревший атрибут, то Компилятор должен выдать предупреждение или ошибка, чтобы предупредить разработчика, таким образом, нарушающий код может быть исправлен. В частности, компилятор должен выдать предупреждение, если нет параметра ошибки или если параметр ошибки предоставляется и имеет значение false. компилятор должен выдать время компиляции ошибка, если параметр ошибки указано и имеет значение true.

В частности, если отмечено значение true, должно появиться сообщение об ошибке, а это не так. Хорошая находка! Вы можете сообщить об этом при «подключении» или, если вам не нужна боль при настройке входа в систему, дайте мне знать, и я с радостью зарегистрирую это (ссылаясь на ваш пост здесь; никаких попыток «украсть» что-либо). 1007 *

(обновление)

Сокращенный код для воспроизведения:

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).

4 голосов
/ 23 февраля 2009

Я согласен с Марком: похоже, ошибка компилятора. Интересно, что 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)
...