왜 Linq 의 Distinct 는 정말 힘 이 되 지 않 습 니까?

5123 단어 linqdistinct
가령 우리 에 게 클래스 가 있다 면:Productpublic class Product{    public string Id { get; set; }    public string Name { get; set; }}주 함 수 는 다음 과 같 습 니 다:static void Main(){    List products = new List()    {        new Product(){ Id="1", Name="n1"},        new Product(){ Id="1", Name="n2"},        new Product(){ Id="2", Name="n1"},        new Product(){ Id="2", Name="n2"},    };    var distinctProduct = products.Distinct();    Console.ReadLine();}distinct 제품 의 결 과 를 볼 수 있 습 니 다imageDistinct 는 기본적으로 제품 대상 의 인용 을 비교 하기 때문에 4 개의 데 이 터 를 되 돌려 줍 니 다.그렇다면 Id 의 유일한 제품 으로 돌아 가 고 싶다 면 어떻게 해 야 할 까? Distinct 방법 은 또 다른 재 부팅 방법 이 있 습 니 다.//지정 한 System.collections.Generic.IEquality Comparer를 사용 하여 값 을 비교//반환 시퀀스 의 비 중복 요 소 를 사용 합 니 다. public static IEnumerable Distinct(this IEnumerable source, IEqualityComparer comparer);이 리 셋 은 IEquality Comparer 의 인 자 를 받 습 니 다.Id 로 선별 하려 면 새 클래스 ProductIdComparer 내용 은 다음 과 같 습 니 다:Public class ProductIdComparer:IEquality Comparer{    public bool Equals(Product x, Product y)    {        if (x == null)            return y == null;        return x.Id == y.Id;    }    public int GetHashCode(Product obj)    {        if (obj == null)            return 0;        return obj.Id.GetHashCode();    }}사용 할 때 var distinctProduct=products.Distinct(new ProductIdComparer())만 필요 합 니 다.결 과 는 다음 과 같다.분명 합 니 다.ProductNameComparer 를 하나 더 추가 해 야 합 니 다.그러면 범 형 류 를 사용 할 수 있 습 니까?새 클래스 PropertyComparer계승 IEquality Comparer내용 은 다음 과 같 습 니 다:public class PropertyComparer:IEquality Comparer{    private PropertyInfo _PropertyInfo;    ///     /// propertyName 을 통 해 PropertyInfo 대상 가 져 오기        ///     ///     public PropertyComparer(string propertyName)    {        _PropertyInfo = typeof(T).GetProperty(propertyName,        BindingFlags.GetProperty | BindingFlags.Instance | BindingFlags.Public);        if (_PropertyInfo == null)        {            throw new ArgumentException(string.Format("{0} is not a property of type {1}.",                 propertyName, typeof(T)));        }    }    #region IEqualityComparer Members    public bool Equals(T x, T y)    {        object xValue = _PropertyInfo.GetValue(x, null);        object yValue = _PropertyInfo.GetValue(y, null);        if (xValue == null)            return yValue == null;        return xValue.Equals(yValue);    }    public int GetHashCode(T obj)    {        object propertyValue = _PropertyInfo.GetValue(obj, null);        if (propertyValue == null)            return 0;        else            return propertyValue.GetHashCode();    }    #endregion}은 주로 재 작성 한 Equals 와 GetHashCode 가 속성의 값 을 사용 하여 비교 합 니 다.사용 할 때://var distinctProduct=products.Distinct(new Property Comparer("Id")만 필요 합 니 다.var distinctProduct = products.Distinct(new PropertyComparer("Name"));결 과 는 다음 과 같다.위의 논리 에 따 르 면 이런 종 류 는 복잡 하지 않 을 것 이다.세심 한 학생 들 은 Property Equality 가 반 사 를 대량으로 사용 한 것 을 발견 할 수 있다.속성의 값 을 가 져 올 때마다 호출PropertyInfo.GetValue(x, null);선별 할 기록 이 많다 면 성능 에 영향 을 미 칠 수 밖 에 없다.성능 을 향상 시 키 기 위해 서 는 표현 식 트 리 를 사용 하여 반사 호출 을 위탁 호출 로 변경 할 수 있 습 니 다.구체 적 인 코드 는 다음 과 같 습 니 다:Public class FastProperty Comparer:IEquality Comparer{    private Func getPropertyValueFunc = null;    ///     /// propertyName 을 통 해 PropertyInfo 대상 가 져 오기    ///     ///     public FastPropertyComparer(string propertyName)    {        PropertyInfo _PropertyInfo = typeof(T).GetProperty(propertyName,        BindingFlags.GetProperty | BindingFlags.Instance | BindingFlags.Public);        if (_PropertyInfo == null)        {            throw new ArgumentException(string.Format("{0} is not a property of type {1}.",                 propertyName, typeof(T)));        }        ParameterExpression expPara = Expression.Parameter(typeof(T), "obj");        MemberExpression me = Expression.Property(expPara, _PropertyInfo);        getPropertyValueFunc = Expression.Lambda>(me, expPara).Compile();    }    #region IEqualityComparer Members    public bool Equals(T x, T y)    {        object xValue = getPropertyValueFunc(x);        object yValue = getPropertyValueFunc(y);        if (xValue == null)            return yValue == null;        return xValue.Equals(yValue);    }    public int GetHashCode(T obj)    {        object propertyValue = getPropertyValueFunc(obj);        if (propertyValue == null)            return 0;        else            return propertyValue.GetHashCode();    }    #endregion}현재 가 져 온 값 은 getProperty Value Func(obj)만 있 으 면 됩 니 다.사용 시:var distinctProduct=products.Distinct(new FastProperty Comparer("Id").ToList();

좋은 웹페이지 즐겨찾기