一、Distinct
Distinct用于测试集合中的元素并忽略重复值。Dintinct既可以在一个序列上调用,也可以在一个实现了IEquallity-Comparer的对象上调用。
【示例】
1.1 定义实体类
using System;
namespace 通过对象的字段找出非重复对象
{
/// <summary>
/// 实体类
/// </summary>
public class Order
{
//使用自动属性时,需记住:自动属性只能实现最基本的设置器和获取器,
//且无法直接引用字段
public int? OrderID { get; set; }
public string CustomerID { get; set; }
public int? EmployeeID { get; set; }
public DateTime? OrderDate { get; set; }
public DateTime? RequireDate { get; set; }
public DateTime? ShippedDate { get; set; }
public int? ShipVia { get; set; }
public decimal? Freight { get; set; }
public string ShipName { get; set; }
public string ShipAddress { get; set; }
public string ShipCity { get; set; }
public string ShipRegion { get; set; }
public string ShipPostalCode { get; set; }
public string ShipCountry { get; set; }
}
}
分析 :使用可空类型,这样就可以给值类型字段赋空值。
1.2 定义一个方法,用于从数据库中取出值、赋值并进行空值处理
/// <summary>
/// 从数据库中取出值放入集合中
/// </summary>
/// <returns></returns>
public static List<Order> GetOrders()
{
//设置连接字符串,最好放在配置文件中
string connectionString = "xxxxxxxxxxxxxxxxxxxxxx";
//定义一个集合,该集合用于存放Order类对象
List<Order> orders = new List<Order>();
using(SqlConnection con=new SqlConnection(connectionString))
{
con.Open();
SqlCommand com = new SqlCommand("select * from Orders");
com.Connection = con;
com.CommandType = CommandType.Text;
SqlDataReader reader = com.ExecuteReader();
while (reader.Read())
{
orders.Add(new Order
{
OrderID = reader.IsDBNull(0) ? null : (int?)reader.GetInt32(0),
CustomerID = reader.IsDBNull(1) ? null : reader.GetString(1),
EmployeeID = reader.IsDBNull(2) ? null : (int?)reader.GetInt32(2),
OrderDate= reader.IsDBNull(3) ? null :(DateTime?)reader.GetDateTime(3),
RequireDate= reader.IsDBNull(4) ? null : (DateTime?)reader.GetDateTime(4),
ShippedDate= reader.IsDBNull(5) ? null : (DateTime?)reader.GetDateTime(5),
ShipVia= reader.IsDBNull(6) ? null : (int?)reader.GetInt32(6),
Freight= reader.IsDBNull(7) ? null : (decimal?)reader.GetDecimal(7),
ShipName= reader.IsDBNull(8) ? null : reader.GetString(8),
ShipAddress= reader.IsDBNull(9) ? null : reader.GetString(9),
ShipCity= reader.IsDBNull(10) ? null : reader.GetString(10),
ShipRegion= reader.IsDBNull(11) ? null : reader.GetString(11),
ShipPostalCode= reader.IsDBNull(12) ? null : reader.GetString(12),
ShipCountry= reader.IsDBNull(13) ? null : reader.GetString(13),
});
}
}
return orders;
}
1.3 实现一个IEqualityComparer
在Order对象上执行自定义的比较操作。
using System.Collections.Generic;
namespace 通过对象的字段找出非重复对象
{
/// <summary>
/// 在Order对象上执行自定义的比较操作
/// </summary>
public class CityComparer : IEqualityComparer<Order>
{
public bool Equals(Order x, Order y)
{
return x.ShipCity == null || y.ShipCity == null ? false : x.ShipCity.Equals(y.ShipCity);
}
public int GetHashCode(Order obj)
{
return obj.ShipCity == null ? -1 : obj.ShipCity.GetHashCode();
}
}
}
1.4 对象转换器
转储器通过一个StringBuilder和发射来获取公共属性(代表着一个对象的状态),然后迭代这些属性并显示各个属性的名称和值。
/// <summary>
/// 一个基于反射和属性的通用对象转储器实用工具
/// </summary>
public static string Dump<T>(T obj)
{
//Type--表示类型声明:类类型、接口类型、数组类型、值类型、枚举类型、类型参数、泛型类型定义,
//以及开放或封闭构造的泛型类型。
Type t = typeof(T);
StringBuilder builder = new StringBuilder();
//GetProperties:返回当前 System.Type 的所有公共属性。
//返回结果:
// 表示当前 System.Type 的所有公共属性的 System.Reflection.PropertyInfo 对象数组。- 或 -如果当前 System.Type
// 没有公共属性,则为 System.Reflection.PropertyInfo 类型的空数组。
PropertyInfo[] infos = t.GetProperties();
Array.ForEach(infos.ToArray(), p => builder.AppendFormat("{0}={1} ", p.Name,
p.GetValue(obj, null) == null ? "" : p.GetValue(obj, null)));
builder.AppendLine();
return builder.ToString();
}
1.5 执行
/// <summary>
/// Demonstrates distinct ship city
/// </summary>
/// <param name="args"></param>
static void Main(string[] args)
{
List<Order> orders = GetOrders();
Array.ForEach(orders.ToArray(), o => Console.WriteLine(Dump(o)));
Console.WriteLine(orders.Count());
//version1 with extension method OrderBy
var cities = orders.Distinct(new CityComparer());
Array.ForEach(cities.OrderBy(o => o.ShipCity).ToArray(),
orderedByCity => Console.WriteLine(orderedByCity.ShipCity));
//version 2 with query
var cities2 = from order in orders.Distinct(new CityComparer())
orderby order.ShipCity
select order;
Array.ForEach(cities2.ToArray(),
orderedByCity => Console.WriteLine(orderedByCity.ShipCity));
Console.WriteLine(cities.Count());
Console.ReadKey();
}
二、通过Intersect和Except定义集合
Intersect扩展方法将参数序列与源序列进行比较,然后返回源序列和目标序列中都有的那些元素。
Except扩展方法返回源序列(调用Except的那个序列)中有而目标序列中没有的那些元素。
【示例】
using System;
using System.Linq;
namespace 计算集合的区别并显示结果
{
class Program
{
static void Main(string[] args)
{
var number1 = new int[] { 2, 3, 4, 5, 12, 23, 34 };
var number2 = new int[] { 3, 125, 23, 43, 54, 65 };
Console.WriteLine("得到源序列中有而目标序列中没有的那些元素:");
var setDifference = number2.Except(number1);
Array.ForEach(setDifference.ToArray(), n => Console.Write(n + " "));
Console.WriteLine();
Console.WriteLine("得到源序列和目标序列中都有的那些元素:");
var setSame = number1.Intersect(number2);
Array.ForEach(setSame.ToArray(), n => Console.Write(n + " "));
Console.ReadKey();
}
}
}
三、Union复合结果集
【示例】
using System;
using System.Linq;
namespace 使用Union创建复合结果集
{
class Program
{
static void Main(string[] args)
{
var number1 = new int[] { 2, 3, 4, 5, 12, 23, 34 };
var number2 = new int[] { 3, 125, 23, 43, 54, 65 };
var union = number1.Union(number2);
Array.ForEach<int>(union.ToArray(), n => Console.Write(n+" "));
Console.WriteLine();
Array.ForEach<int>(union.OrderBy(n => n).ToArray(), n => Console.Write(n + " "));
Console.ReadKey();
}
}
}