Почему свойства коллекции C # не помечаются как устаревшие при вызове свойств для них?
-
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)