c# IEnumerable<object> 绑定到 XDocument 更改
c# IEnumerable<object> is bound to XDocument changes
我有一个 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();
}
}
}
结果是这样的:
IEnumerable
就像数据的承诺,所以只有当你遍历它(或在其上使用类似 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
我有一个 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();
}
}
}
结果是这样的:
IEnumerable
就像数据的承诺,所以只有当你遍历它(或在其上使用类似 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