一、带有函数调用功能的选择
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace 带有函数调用功能的选择
{
class Program
{
static void Main(string[] args)
{
DateTime start = DateTime.Now;
const long upper = 1000000;
var numbers = new long[upper];
for (long i = 2000; i <5000 ; i++)
{
numbers[i] = i + 1;
}
var primes = from n in numbers
where IsPrime(n)
select n;
//BuildPrimes(upper);
//var primes = from n in numbers
// where IsPrime2(n)
// select n;
DateTime stop = DateTime.Now;
StringBuilder builder = new StringBuilder();
Array.ForEach(primes.ToArray(), n => builder.AppendFormat("{0}\n", n));
Console.Write(builder.ToString());
Console.WriteLine("Elapsed:{0}", Elasped(start, stop));
Console.ReadKey();
}
/// <summary>
/// 判断素数方法
/// </summary>
/// <param name="num">大于等于1小于den</param>
/// <param name="den">目标数</param>
/// <returns></returns>
private static long Gcd(long num,long den)
{
return den % num == 1 ? 1 : den % num == 0 ? num : Gcd(den % num, num);
}
/// <summary>
/// 用于观察某个函数执行的时间
/// </summary>
/// <param name="start"></param>
/// <param name="stop"></param>
/// <returns></returns>
private static string Elasped(DateTime start,DateTime stop)
{
TimeSpan span = stop - start;
return string.Format("Days:{0},Hours:{1},Minutes:{2},Seconds:{3},Miles:{4}",
span.Days, span.Hours, span.Minutes, span.Seconds, span.Milliseconds);
}
/// <summary>
/// 判断v是否为素数,以下两种不同办法
/// </summary>
/// <param name="v"></param>
/// <returns></returns>
private static bool IsPrime(long v)
{
if (v <= 1)
return false;
for (long i = 1; i < v; i++)
if (Gcd(i, v) > 1)
return false;
return true;
}
private static bool IsPrime2(long v)
{
for (int i = 0; i < Primes.Count; i++)
{
if (v % Primes[i] == 0)
return false;
if (Primes[i] >= Math.Sqrt(v))
return true;
}
return true;
}
private static List<long> Primes = new List<long>();
private static void BuildPrimes(long max)
{
Primes.Add(2);
if (max < 3)
return;
for (long i = 0; i <= max; i++)
if (IsPrime2(i))
Primes.Add(i);
}
}
}
二、使用Select谓词
Select子句可以通过调用函数的方式进行计算,而这些谓词也可以直接使用。
【示例】
using System;
using System.Linq;
namespace 使用select谓词
{
class Program
{
static void Main(string[] args)
{
var number =new int[]{ 2,3,4,5,6};
var result = from n in number
select n * 2;
//foreach (var item in result)
//{
// Console.Write(item + " ");
//}
Array.ForEach(result.ToArray(), n => Console.Write(n + " "));//2,4,6,8,10
Console.ReadKey();
}
}
}
三、从数据访问层返回自定义业务对象
如何在称之为业务层的地方使用linq?我们需要在查询中构造已知类型而不是匿名类型,而且业务层中的这个函数需要返回IEnuerable<T>对象,其实T就是业务实体。
3.1 定义一个业务实体,并重写ToString()方法,用于转储实体状态
using System;
using System.Linq;
using System.Text;
using System.Reflection;
namespace 通过LINQ返回自定义业务对象
{
/// <summary>
/// 业务实体类
/// </summary>
public class Supplier
{
public int SupplierID { get; set; }
public string CompanyName { get; set; }
public string ContactName { get; set; }
public string ContactTitle { get; set; }
public string Address { get; set; }
public string City { get; set; }
public string Region { get; set; }
public string PostalCode { get; set; }
public string Country { get; set; }
public string Phone { get; set; }
public string Fax { get; set; }
public string HomePage { get; set; }
/// <summary>
/// 转储实体状态
/// </summary>
/// <returns></returns>
public override string ToString()
{
StringBuilder builder = new StringBuilder();
PropertyInfo[] props = this.GetType().GetProperties();
//use array for each
Array.ForEach(props.ToArray(), p => builder.AppendFormat("{0}:{1}", p.Name,
p.GetValue(this, null) == null ? "<empty>\n"
: p.GetValue(this,null).ToString() + "\n"));
return builder.ToString();
}
}
}
3.2 定义IDataReader的扩展方法并有一个泛型委托Func用于提供全部的空值检查
using System;
using System.Data;
namespace 通过LINQ返回自定义业务对象
{
public static class ExtendsReader
{
/// <summary>
/// 泛型委托Func用于提供全部的空值检查
/// </summary>
static Func<string, IDataReader, string, string> SafeRead =
(fieldName, reader, defaultValue) =>
reader[fieldName] != null ? (string)Convert.ChangeType(reader[fieldName],
typeof(string)) : defaultValue;
/// <summary>
/// 调用泛型委托,实现对全部字段的空值检查,这是一个扩展方法
/// </summary>
/// <param name="reader"></param>
/// <returns></returns>
public static Supplier ReadSupplier(this IDataReader reader)
{
Supplier supplier = new Supplier();
supplier.SupplierID = reader.GetInt32(0);
supplier.CompanyName = SafeRead("CompanyName", reader, " ");
supplier.ContactName = SafeRead("ContactName", reader, " ");
supplier.ContactTitle = SafeRead("ContactTitle", reader, " ");
supplier.Address = SafeRead("Address", reader, " ");
supplier.City = SafeRead("City", reader, " ");
supplier.Region = SafeRead("Region", reader, " ");
supplier.PostalCode = SafeRead("PostalCode", reader, " ");
supplier.Country = SafeRead("Country", reader, " ");
supplier.Phone = SafeRead("Phone", reader, " ");
supplier.Fax = SafeRead("fax", reader, " ");
supplier.HomePage = SafeRead("HomePage", reader, " ");
return supplier;
}
}
}
3.3 读取所有供应商的方法
using System;
using System.Collections.Generic;
using System.Linq;
using System.Data;
using System.Data.SqlClient;
namespace 通过LINQ返回自定义业务对象
{
public static class DataAccess
{
private static readonly string connectionString = "Data Source=.; Initial Catalog=pubs; Integrated Security=SSPI;";
/// <summary>
/// 用于读取所有供应商的泛型方法
/// </summary>
/// <param name="predicate">筛选结果集</param>
/// <returns></returns>
public static IEnumerable<Supplier>
ReadSuppliers(Func<Supplier,bool> predicate)
{
IEnumerable<Supplier> suppliers = ReadSuppliers();
return (from s in suppliers select s).Where(predicate);
}
public static IEnumerable<Supplier> ReadSuppliers()
{
using(SqlConnection con=new SqlConnection(connectionString))
{
con.Open();
SqlCommand com = new SqlCommand("select * from suppliers", con);
IDataReader reader = com.ExecuteReader();
List<Supplier> list = new List<Supplier>();
while (reader.Read())
{
list.Add(reader.ReadSupplier());
}
return list;
}
}
}
}
3.4 执行
using System;
using System.Collections.Generic;
using System.Linq;
namespace 通过LINQ返回自定义业务对象
{
class Program
{
static void Main(string[] args)
{
IEnumerable<Supplier> USSuppliers = DataAccess.ReadSuppliers(s => s.Country == "USA");
Array.ForEach(USSuppliers.ToArray(), s => Console.WriteLine(s));
Console.ReadKey();
}
}
}
四、使用Select的索引打乱数组
using System;
using System.Linq;
namespace 使用Select的索引打乱数组
{
class Program
{
static void Main(string[] args)
{
int[] cards = new int[20];
Random random = new Random();
var result = cards.Select((num, index) =>
new { Key = index, Random = random.Next(200) });
Array.ForEach(result.OrderBy(s => s.Random).ToArray(),
s => Console.WriteLine(s));
Console.ReadLine();
}
}
}
五、使用Select将单词的首字母改为大写
using System;
using System.Collections.Generic;
using System.Linq;
namespace LINQ
{
class Program
{
static void Main(string[] args)
{
string str = "my name is xushuai";
var strArray = str.Split(new char[] { ' '}, StringSplitOptions.RemoveEmptyEntries);
var result = from s in strArray select s.Replace(s[0], Convert.ToChar(s[0].ToString().ToUpper()));
result.WriteLineAll();
Console.ReadLine();
}
}
public static class Extender
{
public static void WriteLineAll<T>(this IEnumerable<T> ary)
{
Array.ForEach(ary.ToArray(), item => Console.WriteLine(item));
}
}
}
六、从多个源中投影出新类型
当LINQ查询使用一个或多个源类型中的元素来定义新类型时,就叫做一个投影。编译器会发出一个类,其类名中含有
AnonymousType字样。用于投影出新类型的方法共有两个:Select和SelectMany。当我们在查询中用到了多个from子句时,就会用到SelectMany方法。
【示例】
using System;
using System.Collections.Generic;
using System.Linq;
namespace 从多个源中投影出新类型
{
class Program
{
static void Main(string[] args)
{
List<Customer> listC = new List<Customer>
{
new Customer {ID=1,CompanyName="xiaoxu" },
new Customer {ID=2,CompanyName="daxiang"}
};
List<Order> listO = new List<Order>
{
new Order {ID=1,ItemScription="hahahahahahahah" },
new Order {ID=2,ItemScription="chsihsidjsidjsidj" },
new Order {ID=3,ItemScription="但是都是大祭司大祭司" }
};
var orderInfo = from c in listC
from o in listO
where c.ID == o.ID
//此时,投影出一个新类型(匿名类型),含有一个Name和Item属性
select new { Name = c.CompanyName, Item = o.ItemScription };
Array.ForEach(orderInfo.ToArray(),
i => Console.WriteLine("Company:{0},Item:{1}", i.Name, i.Item));
Console.ReadKey();
}
}
/// <summary>
/// 实体类
/// </summary>
public class Customer
{
public int ID { get; set; }
public string CompanyName { get; set; }
}
/// <summary>
/// 实体类
/// </summary>
public class Order
{
public int ID { get; set; }
public string ItemScription { get; set; }
}
}

七、在SelectMany中使用索引
SelectMany是一个扩展方法,其LINQ关键字是select,支持多个源序列。
【示例】
using System;
using System.Collections.Generic;
using System.Linq;
namespace 在SelectMany中使用索引
{
class Program
{
static void Main(string[] args)
{
List<Customer> listC = new List<Customer>
{
new Customer {ID=1,CompanyName="xiaoxu" },
new Customer {ID=2,CompanyName="daxiang"}
};
List<Order> listO = new List<Order>
{
new Order {ID=1, CustomerID=2,ItemScription="hahahahahahahah" },
new Order {ID=2,CustomerID=3,ItemScription="chsihsidjsidjsidj" },
new Order {ID=3,CustomerID=1,ItemScription="但是都是大祭司大祭司" }
};
var orderInfo = listC.SelectMany(
(c, index) => from o in listO
where o.CustomerID == c.ID
select new
{
Key = index + 1,
Customer = c.CompanyName,
Item = o.ItemScription
});
Array.ForEach(orderInfo.ToArray(), o => Console.WriteLine(
"Key:{0},Name:{1},Item:{2}", o.Key, o.Customer, o.Item));
Console.ReadKey();
}
}
/// <summary>
/// 实体类
/// </summary>
public class Customer
{
public int ID { get; set; }
public string CompanyName { get; set; }
}
/// <summary>
/// 实体类
/// </summary>
public class Order
{
public int ID { get; set; }
public int CustomerID { get; set; }
public string ItemScription { get; set; }
}
}
//上述示例使用了SelectMany的一个重载版本
//public static IEnumerable<TResult> SelectMany<TSource,TResult>(this IEnumerable<TSource> source,Func<TSource,int,TResult> selector)
//{
// //...
//}
