#c# #xml #list #linq #ienumerable
Вопрос:
У меня есть XML-файл следующего вида:
<products>
<product id="1" name="USB Flash Memory 2 GB" />
<product id="2" name="USB Flash Memory 8 GB" />
<product id="3" name="Wireless Multi Media Keyboard" />
</products>
Я XDocument
читал файл и сохранял результат запроса в переменной типа IEnumerable<Product>
.
Если я добавил новый элемент в XDocument
переменную, она обновляется автоматически, поэтому я подумал, что есть какая-то ошибка, поэтому я попробовал это с List<Product>
переменной типа, и это сработало (т. Е. Добавление элемента в XDocument
автоматическое обновление без этого ввода).
Итак, мой вопрос в том, почему IEnumerable
это связано с XDocument
изменениями, в то время List
как это не так ?
Полный Код:
namespace IEnumerableTest
{
public class Product
{
public int ID { get; set; }
public string ProductName { get; set; }
}
}
namespace IEnumerableTest
{
public partial class Form1 : Form
{
static string path = @"Products.xml";
XDocument xDoc = XDocument.Load(path);
IEnumerable<Product> productsEnum;
List<Product> productsList;
public Form1()
{
InitializeComponent();
productsEnum =
from p in xDoc.Descendants("product")
select new Product
{
ID = int.Parse(p.Attribute("id").Value),
ProductName = p.Attribute("name").Value
};
productsList =
(from p in xDoc.Descendants("product")
select new Product
{
ID = int.Parse(p.Attribute("id").Value),
ProductName = p.Attribute("name").Value
}).ToList();
}
void BindDataGridView()
{
dataGridViewEnum.DataSource = productsEnum.ToList();
dataGridViewList.DataSource = productsList;
}
private void Form1_Load(object sender, EventArgs e)
{
BindDataGridView();
}
private void btnAdd_Click(object sender, EventArgs e)
{
XElement newProduct =
new XElement("product",
new XAttribute("id", 4),
new XAttribute("name", "Wireless USB Optical Mouse"));
xDoc.Root.Add(newProduct);
BindDataGridView();
}
}
}
Результат выглядит так:
Комментарии:
1. И
IEnumerable
это похоже на обещание данных, так что только тогда, когда вы зацикливаетесь на них, то есть когда запрос Linq, который у вас здесь, действительно выполняется.2.
ToList
создает копию.IEnumarable
использует исходные ссылки.3. @imsmn Нет, это плохое описание.
4. @DavidG Не стесняйтесь улучшать его, всегда рад описать вещи немного лучше в будущем.
5. @imsmn я уже сделал это в своем комментарии. ToList заставляет запрос выполняться немедленно.
Ответ №1:
An IEnumerable
-это как обещание данных, поэтому только когда вы зацикливаетесь на нем (или используете на нем что-то вроде a ToList
), то есть когда запрос Linq, который у вас здесь, фактически выполняется. Рассмотрим следующий код:
void Main()
{
IEnumerable<int> numbers = Enumerable.Range(1, 5).Select(x => DoubleNumber(x));
Console.WriteLine($"There are {numbers.Count()} numbers that were doubled");
Console.WriteLine($"There are {numbers.Count()} numbers that were doubled");
}
public int DoubleNumber(int value)
{
Console.WriteLine($"Doubling the number {value}");
return value * 2;
}
Вывод из этого на самом деле:
Doubling the number 1
Doubling the number 2
Doubling the number 3
Doubling the number 4
Doubling the number 5
There are 5 numbers that were doubled
Doubling the number 1
Doubling the number 2
Doubling the number 3
Doubling the number 4
Doubling the number 5
There are 5 numbers that were doubled
Обратите внимание, как вся коллекция чисел была рассчитана дважды. Однако, если вы добавите .ToList()
в конец первой строки, это создаст все числа в памяти только один раз и выдаст вам этот вывод:
Doubling the number 1
Doubling the number 2
Doubling the number 3
Doubling the number 4
Doubling the number 5
There are 5 numbers that were doubled
There are 5 numbers that were doubled
Комментарии:
1. Ладно, я понял. Когда я изменил
XDocument
и вызвалproductsEnum
его, он был обновлен, потому что запрос был выполнен снова, но на этот раз сXDocument
обновленным новым элементом.