Комментарии 25
Сократил эту статью до двух предложений:
Почему я ожидал, что A.Except(B)
вернёт пустое множество, а вернулись элементы первой коллекции?
Потому что я не открыл MSDN, не выяснил смысл термина «ссылочный тип», и не знаю, как по умолчанию сравниваются объекты ссылочных типов.
Причём поддерживается саспенс: с первых строк возникает ощущение, что в результирующую коллекцию попали только некоторые из множества файлов в "Моих документах", а статья посвящена тому, что инстансы FileInfo иногда новые, а иногда кешированные.
Финальное разочарование от этого усиливается.
Я бы чуть по-другому перефомулировал:
"Потому что FileInfo
не умеет в сравнение".
По той же причине он не будет работать без кастомного компаратора в словарях, хештаблицах и прочем добре дотнета.
Я вас услышал, в следующий раз я буду более тщательно выбирать макгаффин для своей истории. Было бы здорово услышать ваше мнение о том, как ещё можно было бы сделать пост лучше и интереснее, чтобы я мог повысить свой навык письма.
Вы промахнулись с ответом, под комментарием есть кнопка 'Ответить'
Чтоб сделать пост лучше и интереснее, нужна интересная тема
Это статья от человека, который только начал изучать язык и решил поделиться своим открытием, и которая бесполезна для более менее опытных людей
Полагаю, что это ответ мне, поэтому изложу свои мысли здесь.
Я считаю, что первая проблема этой статьи не в том, что она плохо написана или безынтересна, а в том, что она пропагандирует подход, который мне не кажется правильным.
Смотрите, я полагаю, что этот пост несёт некоторую педагогическую нагрузку, то есть призван обучить людей чему-то. Припоминая известную цитату, людей, по моему мнению, надо обучать ловле рыбы, а не давать им конкретную рыбу.
Так вот, предположим, что я начинающий .NET-девелопер. Я прочёл эту статью, и теперь знаю, как ExceptIterator
сранивает объекты (Вам плюсик, умение читать исходный код фреймворка — полезная вещь).
Возникают вопросы:
1) Распространяются ли мои знания на код X.Where(xItem => Y.All(yItem => xItem != yItem))
?
2) Правильно ли я понял, что лучший способ получить ответы на мои вопросы — пойти закопаться в код фреймворка?
Ваша статья не даёт ответ на первый вопрос (потому что Вы не исследуете общие моменты фреймворка, а рассматриваете исходник конкретного сценария), и даёт неявный положительный ответ на второй. Соответственно, я делаю вывод, что Вы начали учить язык и платформу не с понимания её внутренней логики, а с набрасывания кода в IDE и изучения исходников в случае возникновения проблем. Это гораздо лучше, чем учиться что-то писать по стековерфлоу, но хуже, чем учиться понимать логику (например, по документации).
Поэтому я считаю, что для начинающих разработчиков Ваша статья не полезна, а, наоборот, вредна.
Для остальных она, полагаю, не несёт новой информации.
Отдельно по поводу оформления: все картинки нечитаемы при увеличении.
Было бы более интересно узнать, почему этот метод пересчитывает хеш сравниваемых объектов каждый раз заново и не кеширует внутри себя. Как то раз, я начал кешировать хеш внутри объекта и уменьшил время работы функции с часа до 20 секунд. Не знал эту фишку, думал это очевидно, что во время Except объекты в коллекций изменяться не будут и значит их хеш не будет изменяться, значит его можно сохранить и не считать заново каждый раз.
Очень грустно, что вы не знаете, что для всех действий, предполагающих сравнение объектов (а не примитивов), надо первым делом смотреть на компареры. Делаем хэшсет? Смотрим на компарер. Делаем словарь, где объект в ключе? Смотрим на компарер.
Дело не в Except и не в Union. Дело реально в реализации компарера, как и написали выше. Акцент в статье не там.
var documentsDir = new DirectoryInfo(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments));
var FirstDirrectoryFiles = documentsDir.GetFiles().Select(a=> a.Name);
var SecondDirrectoryFiles = documentsDir.GetFiles().Select(a => a.Name);
foreach (var item in FirstDirrectoryFiles.Except(SecondDirrectoryFiles))
Console.WriteLine(item);
Это во-первых: https://docs.microsoft.com/en-us/dotnet/csharp/fundamentals/coding-style/coding-conventions#implicitly-typed-local-variables
А во-вторых, это буквально тоже самое, что и код в статье
Не воспринимайте слишком серьёзно рекомендации майков, они сами не всегда их соблюдают.
На практике явное указание типов, по моему опыту, используется крайне редко
Тут за неявным указанием типов спрятали то, что на выходе у нас IEnumerable<string>, а не IEnumerable<FileInfo>. Да и в целом, как по мне, эти рекомендации не про то, что var зло и его не надо использовать, а про то, что он не должен усложнять понимание кода. Это скорее ближе к питоновскому "Явное лучше неявного".
Вас сильно удивит результат "того же самого" кода.
var documentsDir = new DirectoryInfo(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments));
FileInfo[] result1 = documentsDir.GetFiles();
FileInfo[] result2 = documentsDir.GetFiles();
foreach (FileInfo item in result1
.Select(i => i.FullName)
.Except(result2.Select(i => i.FullName))
.Select(i => new FileInfo(i)))
{
Console.WriteLine(item.Name);
}
Вот вам код из статьи. Ваш отличается лишь тем, что вы вынесли Select чуть выше по коду. Быть может вы просто не заметили его из-за того, что он спрятан в спойлере почти в конце поста.
Сравните не с этим кодом, а с тем что постили в самом начале статьи.
Так статья и посвящена тому, почему тот вариант не работает, а в конце приведены три рабочих варианта.
Я подправил ваш код так как бы вы хотели, как бы он работал. Дальше читать статью смысла не было. Если вы сами поняли свою ошибку, то стоило вообще удалить эту статью, так как она бессмысленна и строится из-за изначального непонимания как сравниваются элементы.
Я вот предположил, что ничего, потому что Except должен вычитать множество (IEnumerable) правого аргумента из множества (IEnumerable) левого аргумента. Однако, вопреки моим ожиданиям я получил:
Видимо, только вы один предположили это.
all my friends are toxic (c) BoyWithUke - Toxic
Except в Linq