最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

為何Linq的Distinct實在是不給力

 更新時間:2013年05月13日 17:56:07   作者:  
本篇文章對Linq的Distinct進行了詳細的分析介紹,需要的朋友參考下
假設(shè)我們有一個類:Product

public class Product
{
    public string Id { get; set; }
    public string Name { get; set; }
}
Main函數(shù)如下:
static void Main()
{
    List<Product> products = new List<Product>()
    {
        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();
}
可以看到distinctProduct 的結(jié)果是:

image

因為Distinct 默認比較的是Product對象的引用,所以返回4條數(shù)據(jù)。
那么如果我們希望返回Id唯一的product,那么該如何做呢?
 
Distinct方法還有另一個重載:
//通過使用指定的 System.Collections.Generic.IEqualityComparer<T> 對值進行比較
//返回序列中的非重復(fù)元素。
 public static IEnumerable<TSource> Distinct<TSource>(this IEnumerable<TSource> source,
IEqualityComparer<TSource> comparer);
該重載接收一個IEqualityComparer的參數(shù)。
假設(shè)要按Id來篩選,那么應(yīng)該新建類ProductIdComparer 內(nèi)容如下:
public class ProductIdComparer : IEqualityComparer<Product>
{
    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());
結(jié)果如下:

image

現(xiàn)在假設(shè)我們要 按照 Name來篩選重復(fù)呢?
很明顯,需要再添加一個類ProductNameComparer.
那能不能使用泛型類呢??
新建類PropertyComparer<T> 繼承IEqualityComparer<T> 內(nèi)容如下:
public class PropertyComparer<T> : IEqualityComparer<T>
{
    private PropertyInfo _PropertyInfo;
    /// <summary>
    /// 通過propertyName 獲取PropertyInfo對象   
    /// </summary>
    /// <param name="propertyName"></param>
    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<T> 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 PropertyComparer<Product>("Id"));
var distinctProduct = products.Distinct(new PropertyComparer<Product>("Name"));

結(jié)果如下:

image

為什么微軟不提供PropertyEquality<T> 這個類呢?
按照上面的邏輯,這個類應(yīng)該沒有很復(fù)雜啊,細心的同學(xué)可以發(fā)現(xiàn)PropertyEquality 大量的使用了反射。每次獲取屬性的值的時候,都在調(diào)用
_PropertyInfo.GetValue(x, null);
可想而知,如果要篩選的記錄非常多的話,那么性能無疑會受到影響。
為了提升性能,可以使用表達式樹將反射調(diào)用改為委托調(diào)用,
具體代碼如下:

public class FastPropertyComparer<T> : IEqualityComparer<T>
{
    private Func<T, Object> getPropertyValueFunc = null;
    /// <summary>
    /// 通過propertyName 獲取PropertyInfo對象
    /// </summary>
    /// <param name="propertyName"></param>
    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<Func<T, object>>(me, expPara).Compile();
    }
    #region IEqualityComparer<T> 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
}

可以看到現(xiàn)在獲取值只需要getPropertyValueFunc(obj) 就可以了。
使用的時候:
var distinctProduct = products.Distinct(new FastPropertyComparer<Product>("Id")).ToList();

相關(guān)文章

  • C#實現(xiàn)過濾sql特殊字符的方法集合

    C#實現(xiàn)過濾sql特殊字符的方法集合

    這篇文章主要介紹了C#實現(xiàn)過濾sql特殊字符的方法,以實例形式分析總結(jié)了C#針對SQL危險字符的幾種常用的過濾技巧,非常具有實用價值,需要的朋友可以參考下
    2015-11-11
  • C#構(gòu)建樹形結(jié)構(gòu)數(shù)據(jù)(全部構(gòu)建,查找構(gòu)建)

    C#構(gòu)建樹形結(jié)構(gòu)數(shù)據(jù)(全部構(gòu)建,查找構(gòu)建)

    這篇文章主要介紹了C#構(gòu)建樹形結(jié)構(gòu)數(shù)據(jù)(全部構(gòu)建,查找構(gòu)建),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-10-10
  • C#中dotnetcharting的用法實例詳解

    C#中dotnetcharting的用法實例詳解

    這篇文章主要介紹了C#中dotnetcharting的用法,以實例形式詳細分析了基于dotnetcharting的圖表繪制的各種常用方法,是非常實用的技巧,需要的朋友可以參考下
    2014-10-10
  • C#調(diào)用VB進行簡繁轉(zhuǎn)換的方法

    C#調(diào)用VB進行簡繁轉(zhuǎn)換的方法

    這篇文章主要介紹了C#調(diào)用VB進行簡繁轉(zhuǎn)換的方法,通過調(diào)用VB的動態(tài)鏈接庫實現(xiàn)繁簡轉(zhuǎn)換的技巧,非常具有實用價值,需要的朋友可以參考下
    2015-02-02
  • C# LINQ查詢表達式及對應(yīng)LAMBDA表達式的用法

    C# LINQ查詢表達式及對應(yīng)LAMBDA表達式的用法

    這篇文章主要介紹了C# LINQ查詢表達式及對應(yīng)LAMBDA表達式的用法,幫助大家更好的理解和學(xué)習(xí)使用c#,感興趣的朋友可以了解下
    2021-04-04
  • 詳解C#中線程傳參,返回值和多線程沖突問題的解決

    詳解C#中線程傳參,返回值和多線程沖突問題的解決

    這篇文章主要為大家詳細介紹了C#中線程傳參,返回值和多線程沖突問題的解決方法,文中的示例代碼講解詳細,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2022-11-11
  • C#中使用gRPC通訊的示例詳解

    C#中使用gRPC通訊的示例詳解

    這篇文章主要為大家詳細介紹了C#中如何使用gRPC通訊,包括GRPC文件的創(chuàng)建生成、服務(wù)端和客戶端函數(shù)類庫的封裝等,需要的可以了解下
    2024-04-04
  • Unity中協(xié)程IEnumerator的使用方法介紹詳解

    Unity中協(xié)程IEnumerator的使用方法介紹詳解

    本文主要介紹了Unity中協(xié)程IEnumerator的使用方法介紹詳解,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-06-06
  • C#處理文本文件TXT實例詳解

    C#處理文本文件TXT實例詳解

    這篇文章主要介紹了C#處理文本文件TXT的方法,以實例形式詳細分析了txt文本文件的讀取、修改及打印等功能的實現(xiàn)技巧,需要的朋友可以參考下
    2015-02-02
  • 基于數(shù)據(jù)類型轉(zhuǎn)換(裝箱與拆箱)與常量詳解

    基于數(shù)據(jù)類型轉(zhuǎn)換(裝箱與拆箱)與常量詳解

    下面小編就為大家分享一篇基于數(shù)據(jù)類型轉(zhuǎn)換(裝箱與拆箱)與常量詳解,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2017-11-11

最新評論

冀州市| 确山县| 中牟县| 章丘市| 湟中县| 玉环县| 广水市| 南宫市| 铜陵市| 新干县| 临湘市| 涟源市| 莒南县| 博乐市| 太白县| 班戈县| 马关县| 砚山县| 金溪县| 漳州市| 香港 | 拉萨市| 鄱阳县| 凌海市| 弥渡县| 宜宾市| 达孜县| 福鼎市| 永寿县| 崇左市| 山西省| 和静县| 台州市| 海安县| 四川省| 赤壁市| 临清市| 曲松县| 汽车| 辉县市| 固原市|