В вашем решении есть две проблемы.
Поведение ToString ()
При выполнении .ToString () в IEnumerable он всегда выводит тип. Это связано с тем, что IEnumerable не переопределяет поведение ToString (). См. ToString для получения дополнительной информации об этом.
Если вы хотите преобразовать IEnumerable (возвращаемый тип Except) в строку, вам нужно будет сделать
var C = new string(A.Except(B));
Поведение А. За исключением (B)
Метод Except не совсем работает так, как вы думаете.
Возьмем для примера следующий код:
var a = new List<int> { 1, 2, 3 };
var b = new List<int> { 2, 3, 4 };
var c = a.Except(b);
Результатом этого будет {1}. Что эффективно делает метод, так это возвращает новое перечисление всех целых чисел, присутствующих в a, но не в b.
Теперь строки - это просто перечисление символов - точнее, ваш
var A = "<div><p>One</p><p>Two</p></div>";
с точки зрения LINQ, эквивалентно
var A = new List<char> { '<', 'd', 'i', 'v', '>', ..., '<', '/', 'd', 'i', 'v', '>' };
То же самое относится и к B.
Таким образом, когда вы выполняете A.Except (B), LINQ на самом деле будет проходить через каждый символ и смотреть, сможет ли он найти его в B. Если это произойдет, он не окажется в наборе результатов. Теперь, поскольку все символы в A также присутствуют в B, вы получите пустую строку. Чтобы увидеть, что это действительно так, слегка измените A, чтобы он содержал символ, которого нет в B:
string A = "<div><p>One</p><p>Two</p></div>ApplePie";
Если вы сейчас делаете
string A = "<div><p>One</p><p>Two</p></div>ApplePie";
string B = "<div><p>One</p><p>Two</p><p>Three</p></div>";
string C = new string(A.Except(B).ToArray());
вы получите "AlP".
Решение
На мой взгляд, лучший способ сделать что-либо кроме анализа - это проанализировать ваши строки, преобразовать их в объекты, а затем выполнить исключение. Ни один встроенный алгоритм не может сказать, что ваши строки действительно структурированы и как их различать. И в качестве рабочего решения, используя HtmlAgilityPack (пакет nuget)
var docB = new HtmlDocument();
docB.LoadHtml(B);
var docA = new HtmlDocument();
docA.LoadHtml(A);
var nodes = docB.DocumentNode.FirstChild.Descendants("p").Select(node => node.InnerHtml)
.Except(docA.DocumentNode.FirstChild.ChildNodes.Select(node => node.InnerHtml));
// take note that we are actually doing whatIsInB.Except(whatIsInA), since doing the reverse would result in nothing. There is no <p> in A that is not also present in B
var result = string.Join(Environment.NewLine, nodes); // will resut in "Three"
var otherResult = $"<p>{result}</p>"; // "<p>Three</p>"
Я позволю вам сделать более общий подход:)
Но идея в том, что если вы хотите работать иначе, чем ожидаете, вам придется попросить его работать со строками, а не с символами.
Делаете ли вы синтаксический анализ, необходимый для извлечения компонентов вашей строки (элементы
в этом примере), используя HtmlAgilityPack или Regex, как это предлагается в других решениях, полностью зависит от вас.