【问题标题】:c# IEnumerable<object> is bound to XDocument changesc# IEnumerable<object> 绑定到 XDocument 更改
【发布时间】:2021-10-08 10:59:09
【问题描述】:

我有一个如下的 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&lt;Product&gt; 类型的变量中。

如果我向XDocument 添加了一个新元素,该变量会自动更新,所以我认为存在一些错误,所以我尝试使用List&lt;Product&gt; 类型变量并且它有效(即向@987654328 添加一个元素@不要使用该输入自动更新)

所以我的问题是为什么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 就像一个数据的承诺,所以只有当你循环它时,你这里的Linq 查询才会真正执行。
  • ToList 创建一个副本。 IEnumarable 使用原始引用。
  • @imsmn 不,这是一个糟糕的描述。
  • @DavidG 随时改进它,总是很高兴能在未来更好地描述事物。
  • @imsmn 我已经在我的评论中做了。 ToList 正在强制查询立即执行。

标签: c# xml list linq ienumerable


【解决方案1】:

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

【讨论】:

  • 好的,我明白了。当我更改XDocument 并调用productsEnum 时,它已更新,因为查询再次运行,但这次XDocument 更新了新元素。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-25
  • 2023-04-10
  • 2011-02-09
  • 2023-03-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多