Почему IntelliSense не работает должным образом в цикле foreach?

1

Набрав следующий фрагмент кода, я заметил, что Intellisense не работает должным образом:

StringBuilder sb = new StringBuilder();

foreach (PropertyDescriptor prop in TypeDescriptor.GetProperties(sb))
{
    var name = prop.DisplayName;
    Console.WriteLine("{0}", name);
}

В предложении foreach, если я начну печатать prop.Di, Intellisense завершится как expexcted с prop.DisplayName. Однако я использую ключевое слово var вместо PropertyDescriptor, тогда я вижу только метод, унаследованный от объекта.

Поскольку TypeDescriptor.GetProperties() возвращает коллекцию TypeDescriptor, я думал, что Visual Studio сможет вывести правильный тип для prop.

Почему это не работает?

Теги:
visual-studio
intellisense

2 ответа

8
Лучший ответ

GetProperties возвращает PropertyDescriptorCollection который реализует только IEnumerable, а не IEnumerable<PropertyDescriptor>. Если вы используете var, тип prop определяется как object не PropertyDescriptor.

4

Он возвращает PropertyDescriptorCollection, а возвращаемый тип метода GetEnumerator PropertyDescriptorCollection - IEnumerator (не общий). Так что даже вы можете написать

foreach (int prop in TypeDescriptor.GetProperties(sb))

И вы не получите никаких исключений во время компиляции, но во время выполнения вы получите InvalidCastException.

Вот пример, демонстрирующий разницу:

Обычно это недопустимо:

foreach(string x in new List<int>())

Поскольку List<T> реализует IEnumerable<T> Но если вы оберните его классом и реализуете не общий интерфейс IEnumerable:

class NonGenericCollection : IEnumerable
{
    public List<int> List { get; set; }


    public NonGenericCollection()
    {
        List = new List<int>();
    }

    public IEnumerator GetEnumerator()
    {
        return List.GetEnumerator();
    }
}

Вы можете написать любой тип, который вы хотите, и не получать никаких исключений во время компиляции:

foreach(string x in new NonGenericCollection())

Поскольку тип возвращаемого значения выводится как объект, а фактический тип неизвестен до времени выполнения.

  • 0
    foreach(string x in new List<int>()) недопустима, потому что нет преобразования типа int в строку, а не потому, что List<T> реализует IEnumerable<T> . Измените List<int> на List<object> и у компилятора нет возражений.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню