浅析c#范型中的特殊关键字where default
将字符串类型和整型分开处理(用到了表达式树):
using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Reflection;
/// <summary>
/// 泛型集合或对象通过字符串类型属性值比较是否相同
/// </summary>
/// <typeparam name="T"></typeparam>
public class CollectionsPropertyComparer<T> : IEqualityComparer<T>
{
//委托
Func<T, object> propertyValue = null;
public CollectionsPropertyComparer(string propertyName)
{
PropertyInfo propertyInfo = typeof(T).GetProperty(propertyName, BindingFlags.Public | BindingFlags.Instance | BindingFlags.GetProperty);
if (propertyInfo == null)
{
throw new ArgumentException(string.Format("{0} is not the property of {1} type ", propertyName,typeof(T)));
}
//使用表达式树获取属性值
//参数
ParameterExpression pe= Expression.Parameter(typeof(T), "obj");
//创建一个访问属性
MemberExpression me= Expression.Property(pe, propertyInfo);
//编译返回lambda委托
Type type = me.GetType();
propertyValue = Expression.Lambda<Func<T,object>>(me,pe).Compile();
}
public bool Equals(T x, T y)
{
if (x == null)
return y == null;
//获取对象属性值进行比较
object xValue = propertyValue(x);
object yValue = propertyValue(y);
return xValue == yValue;
}
public int GetHashCode(T obj)
{
if (obj == null)
return 0;
object value = propertyValue(obj);
return value.GetHashCode();
}
}
/// <summary>
/// 泛型集合或对象通过整数类型属性值比较是否相同
/// </summary>
/// <typeparam name="T"></typeparam>
public class CollectionsInt32PropertyComparer<T> : IEqualityComparer<T>
{
//委托
Func<T, int> propertyValue = null;
public CollectionsInt32PropertyComparer(string propertyName)
{
PropertyInfo propertyInfo = typeof(T).GetProperty(propertyName, BindingFlags.Public | BindingFlags.Instance | BindingFlags.GetProperty);
if (propertyInfo == null)
{
throw new ArgumentException(string.Format("{0} is not the property of type {1} ", propertyName, typeof(T)));
}
//使用表达式树获取属性值
//参数
ParameterExpression pe = Expression.Parameter(typeof(T), "obj");
//创建一个访问属性
MemberExpression me = Expression.Property(pe, propertyInfo);
//编译返回lambda委托
Type type = me.GetType();
propertyValue = Expression.Lambda<Func<T, int>>(me, pe).Compile();
}
public bool Equals(T x, T y)
{
if (x == null)
return y == null;
//获取对象属性值进行比较
int xValue = propertyValue(x);
int yValue = propertyValue(y);
return xValue == yValue;
}
public int GetHashCode(T obj)
{
if (obj == null)
return 0;
object value = propertyValue(obj);
return value.GetHashCode();
}
}
测试示例:
public partial class TS : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
List<Student> students = new List<Student> {
new Student{ ID=1, StuID ="1", StuName="test1", Age=20},
new Student{ ID=1,StuID="1", StuName="test1", Age=21},
new Student{ ID=2,StuID="2", StuName="test2", Age=22},
new Student{ ID=3,StuID="3", StuName="test2", Age=22},
new Student{ ID=1,StuID="1", StuName="test2", Age=23}
};
var cp_studid= new CollectionsInt32PropertyComparer<Student>("ID");
var cp_studname = new CollectionsPropertyComparer<Student>("StuName");
//集合根据不同属性过滤相同记录
var list_stuid = students.Distinct(cp_studid).ToList(); //集合索引为:0,2,3
var list_stuname = students.Distinct(cp_studname).ToList(); //集合索引为:0,2
//单个实体根据不同属性比较相等
var stuA = new Student { ID = 1, StuID = "1", StuName = "test1", Age = 20 };
var stuB = new Student { ID = 1, StuID = "1", StuName = "test2", Age = 20 };
var stuC = new Student { ID = 2, StuID = "2", StuName = "test2", Age = 20 };
bool ab = cp_studid.Equals(stuA, stuB); //true
bool ac = cp_studid.Equals(stuA, stuC);//false
bool bc = cp_studname.Equals(stuB, stuC);//true
}
}
}
public class Student
{
public int ID { get; set; }
public string StuID { get; set; }
public string StuName { get; set; }
public int Age { get; set; }
}