C# 使用Linq Select查询或For循环搜索泛型列表中的内容,哪种方法更好?
就性能而言,C# 使用Linq Select查询或For循环搜索泛型列表中的内容,哪种方法更好?,c#,.net,linq,C#,.net,Linq,就性能而言, Linq Select Query或For Loop哪种方法在泛型列表中搜索内容更好?AFor循环可能会稍微快一点。测量它以确定。。。但再看看可读性。(编辑:当您测量它时,尝试这样做的时间要比公认答案中的基准测试的时间长。还要将这段代码所花费的时间与程序其余部分的时间进行比较。这真的是一个瓶颈吗?) 我通常不会使用“select”,除非您实际需要投影一系列结果。要查找单个元素,请使用: list.Find(x => x.Name == "Foo"); 或 我相信这两种方法都
Linq Select Query或For Loop哪种方法在泛型列表中搜索内容更好?A
For
循环可能会稍微快一点。测量它以确定。。。但再看看可读性。(编辑:当您测量它时,尝试这样做的时间要比公认答案中的基准测试的时间长。还要将这段代码所花费的时间与程序其余部分的时间进行比较。这真的是一个瓶颈吗?)
我通常不会使用“select”,除非您实际需要投影一系列结果。要查找单个元素,请使用:
list.Find(x => x.Name == "Foo");
或
我相信这两种方法都比相应的for
循环更具可读性。如果您只是在寻找一个对象,那么您可能需要考虑使用<代码> HasStuts<代码>,或者与列表结合使用。
编辑:这里有一个测试基准。代码在结果下面
c:\Users\Jon\Test>test 1000000 500000 1000
FindCustomerLinq: 28531
FindCustomerListFind: 12315
FindCustomerForLoop: 9737
FindCustomerForEachLoop: 14743
这是在一个包含一百万个元素的列表中,找到了一半,但做了1000次。所以是的,for循环的速度实际上是原来的三倍。。。但在这种差异变得显著之前,你必须做很多。如果你经常做这类事情,你应该寻找其他的选择,比如字典
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
public class Customer
{
public int ID { get; set; }
public string Name { get; set; }
public string Address { get; set; }
public string Phone { get; set; }
}
class Test
{
static void Main(string[] args)
{
int size = int.Parse(args[0]);
int id = int.Parse(args[1]);
int iterations = int.Parse(args[2]);
var list = new List<Customer>(size);
for (int i=0; i < size; i++)
{
list.Add(new Customer {
ID = i,
Address = "Address " + i,
Name = "Cusomer Name " + i,
Phone= "Phone " + i,
});
}
Time(FindCustomerLinq, list, id, iterations);
Time(FindCustomerListFind, list, id, iterations);
Time(FindCustomerForLoop, list, id, iterations);
Time(FindCustomerForEachLoop, list, id, iterations);
}
static void Time(Func<List<Customer>, int, Customer> action,
List<Customer> list,
int id, int iterations)
{
Stopwatch sw = Stopwatch.StartNew();
for (int i=0; i < iterations; i++)
{
action(list, id);
}
sw.Stop();
Console.WriteLine("{0}: {1}", action.Method.Name, (int) sw.ElapsedMilliseconds);
}
static Customer FindCustomerLinq(List<Customer> customers, int id)
{
return customers.FirstOrDefault(c => c.ID == id);
}
static Customer FindCustomerListFind(List<Customer> customers, int id)
{
return customers.Find(c => c.ID == id);
}
static Customer FindCustomerForLoop(List<Customer> customers, int id)
{
for (int i=0; i < customers.Count; i++)
{
if (customers[i].ID == id)
{
return customers[i];
}
}
return null;
}
static Customer FindCustomerForEachLoop(List<Customer> customers, int id)
{
foreach (Customer c in customers)
{
if (c.ID == id)
{
return c;
}
}
return null;
}
}
使用系统;
使用System.Collections.Generic;
使用系统诊断;
使用System.Linq;
公共类客户
{
公共int ID{get;set;}
公共字符串名称{get;set;}
公共字符串地址{get;set;}
公用字符串电话{get;set;}
}
课堂测试
{
静态void Main(字符串[]参数)
{
int size=int.Parse(args[0]);
int id=int.Parse(args[1]);
int迭代=int.Parse(args[2]);
var列表=新列表(大小);
对于(int i=0;ic.ID==ID);
}
静态客户FindCustomerListFind(列出客户,int id)
{
返回customers.Find(c=>c.ID==ID);
}
静态客户FindCustomerForLoop(列出客户,int id)
{
for(int i=0;i
几天前,我对50000条记录进行了与研发相同的尝试,结果发现
for循环所花费的时间约为linq where子句所花费时间的60%
Linq的运行时间:87毫秒
Linq的运行时间:48毫秒
Linq的运行时间:143毫秒
Linq的运行时间:76毫秒
等等。。有关详细信息,请参阅代码我是如何做到的
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Diagnostics;
namespace SearchingList
{
public partial class Form1 : Form
{
private int searchingID = 0;
public int SearchingID
{
get
{
if (string.IsNullOrEmpty(txtID.Text))
searchingID = 0;
else
int.TryParse(txtID.Text, out searchingID);
return searchingID;
}
set
{
SearchingID = searchingID;
}
}
public Form1()
{
InitializeComponent();
}
private void btnsearch_Click(object sender, EventArgs e)
{
List<Customer> lstcustomersFound = new List<Customer>();
Stopwatch stp = new Stopwatch();
stp.Start();
lstcustomersFound = GetSearchedCustomersByLinq(SearchingID, (List<Customer>)dgvAllData.DataSource);
stp.Stop();
lblLinq.Text = "Elapsed Time Linq : " + stp.ElapsedMilliseconds.ToString() + " ms";
stp.Start();
lstcustomersFound = GetSearchedCustomersByForLoop(SearchingID, (List<Customer>)dgvAllData.DataSource);
stp.Stop();
lblFor.Text ="Elapsed Time for loop : " + stp.ElapsedMilliseconds.ToString() + " ms";
dgvSearched.DataSource = lstcustomersFound;
}
private List<Customer> GetSearchedCustomersByForLoop(int searchingID, List<Customer> lstcustomers)
{
List<Customer> lstcustomersFound = new List<Customer>();
foreach (Customer customer in lstcustomers)
{
if (customer.CusomerID.ToString().Contains(searchingID.ToString()))
{
lstcustomersFound.Add(customer);
}
}
return lstcustomersFound;
}
private List<Customer> GetSearchedCustomersByLinq(int searchingID, List<Customer> lstcustomers)
{
var query = from customer in lstcustomers
where customer.CusomerID.ToString().Contains(searchingID.ToString())
select customer as Customer;
return query.ToList();
}
private void Form1_Load(object sender, EventArgs e)
{
List<Customer> customers = new List<Customer>();
Customer customer;
for (int id = 1; id <= 50000; id++)
{
customer = new Customer();
customer.CusomerAddress = "Address " + id.ToString();
customer.CusomerID = id;
customer.CusomerName = "Cusomer Name " + id.ToString();
customer.CusomerPhone= "Phone " + id.ToString();
customers.Add(customer);
}
dgvAllData.DataSource = customers;
}
}
}
由于性能是考虑因素,我将选择for Loop而不是Linq查看搜索“Linq performance”时通常会遇到的无数问题。这是复制列表,而不是查找特定条目。我还认为,你们测量的时间太短,这些结果没有意义。你的情况也很可疑-寻找“10”会找到“100”例如。。。为什么在循环的每次迭代中都要将searchingID转换为字符串?我知道你在这两种情况下都在做同样的事情,但即使如此,我也不会把它作为一个好的基准。我可能遗漏了一些东西,但你不需要在某个地方重置秒表吗?我又创建了一个程序,没有发布在这里,其中customerId是一个字符串,可以根据customerId文本框中更改的文本填充搜索结果。性能结果几乎相同
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Diagnostics;
namespace SearchingList
{
public partial class Form1 : Form
{
private int searchingID = 0;
public int SearchingID
{
get
{
if (string.IsNullOrEmpty(txtID.Text))
searchingID = 0;
else
int.TryParse(txtID.Text, out searchingID);
return searchingID;
}
set
{
SearchingID = searchingID;
}
}
public Form1()
{
InitializeComponent();
}
private void btnsearch_Click(object sender, EventArgs e)
{
List<Customer> lstcustomersFound = new List<Customer>();
Stopwatch stp = new Stopwatch();
stp.Start();
lstcustomersFound = GetSearchedCustomersByLinq(SearchingID, (List<Customer>)dgvAllData.DataSource);
stp.Stop();
lblLinq.Text = "Elapsed Time Linq : " + stp.ElapsedMilliseconds.ToString() + " ms";
stp.Start();
lstcustomersFound = GetSearchedCustomersByForLoop(SearchingID, (List<Customer>)dgvAllData.DataSource);
stp.Stop();
lblFor.Text ="Elapsed Time for loop : " + stp.ElapsedMilliseconds.ToString() + " ms";
dgvSearched.DataSource = lstcustomersFound;
}
private List<Customer> GetSearchedCustomersByForLoop(int searchingID, List<Customer> lstcustomers)
{
List<Customer> lstcustomersFound = new List<Customer>();
foreach (Customer customer in lstcustomers)
{
if (customer.CusomerID.ToString().Contains(searchingID.ToString()))
{
lstcustomersFound.Add(customer);
}
}
return lstcustomersFound;
}
private List<Customer> GetSearchedCustomersByLinq(int searchingID, List<Customer> lstcustomers)
{
var query = from customer in lstcustomers
where customer.CusomerID.ToString().Contains(searchingID.ToString())
select customer as Customer;
return query.ToList();
}
private void Form1_Load(object sender, EventArgs e)
{
List<Customer> customers = new List<Customer>();
Customer customer;
for (int id = 1; id <= 50000; id++)
{
customer = new Customer();
customer.CusomerAddress = "Address " + id.ToString();
customer.CusomerID = id;
customer.CusomerName = "Cusomer Name " + id.ToString();
customer.CusomerPhone= "Phone " + id.ToString();
customers.Add(customer);
}
dgvAllData.DataSource = customers;
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace SearchingList
{
public class Customer
{
public int CusomerID { get; set; }
public string CusomerName { get; set; }
public string CusomerAddress { get; set; }
public string CusomerPhone { get; set; }
}
}