亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > C# > 正文

為何Linq的Distinct實在是不給力

2020-01-24 03:20:50
字體:
來源:轉載
供稿:網友
假設我們有一個類:Product

public class Product
{
    public string Id { get; set; }
    public string Name { get; set; }
}
Main函數如下:
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 的結果是:

image

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

image

現在假設我們要 按照 Name來篩選重復呢?
很明顯,需要再添加一個類ProductNameComparer.
那能不能使用泛型類呢??
新建類PropertyComparer<T> 繼承IEqualityComparer<T> 內容如下:
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"));

結果如下:

image

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

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
}

可以看到現在獲取值只需要getPropertyValueFunc(obj) 就可以了。
使用的時候:
var distinctProduct = products.Distinct(new FastPropertyComparer<Product>("Id")).ToList();
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
国语自产精品视频在线看| 国产精品aaaa| 午夜精品视频网站| 亚洲欧美三级伦理| www.99久久热国产日韩欧美.com| 一区二区三区无码高清视频| 亚洲精品视频网上网址在线观看| 91免费看国产| 国内精品模特av私拍在线观看| 欧美性猛交99久久久久99按摩| 色噜噜狠狠色综合网图区| 在线日韩av观看| 日韩性生活视频| 性金发美女69hd大尺寸| 亚洲天堂日韩电影| 狠狠久久五月精品中文字幕| 综合网日日天干夜夜久久| 91久久精品一区| 国产精品国产福利国产秒拍| 欧美老少做受xxxx高潮| 欧美理论电影在线播放| 成年人精品视频| 日韩美女在线看| 国产一区二区三区在线播放免费观看| 性色av一区二区三区免费| 亚洲午夜激情免费视频| 日韩最新免费不卡| 国内精品国产三级国产在线专| 欧美午夜激情小视频| 国产精品国产自产拍高清av水多| 欧美成人在线免费视频| 68精品国产免费久久久久久婷婷| 亚洲风情亚aⅴ在线发布| 精品女厕一区二区三区| 欧美日韩xxxxx| 久久亚洲一区二区三区四区五区高| 在线视频日本亚洲性| 欧美精品成人91久久久久久久| 欧美另类老肥妇| 欧美性生交xxxxxdddd| 国产成人免费91av在线| 97在线精品视频| 国外成人性视频| 国产精品免费观看在线| 中文字幕av一区二区三区谷原希美| 亚洲香蕉av在线一区二区三区| 少妇久久久久久| 亚洲免费中文字幕| 97超碰国产精品女人人人爽| 成人黄色影片在线| 欧美精品久久久久久久| 欧美性猛交xxxxx水多| 日韩在线观看高清| 亚洲人成电影网站色| 国产精品一久久香蕉国产线看观看| 亚洲一区精品电影| 亚洲国产日韩欧美在线图片| 九九热这里只有精品免费看| 青青草原成人在线视频| 亚洲专区在线视频| 久久久久久亚洲精品| 亚洲欧美日韩在线一区| 国产精品久久网| 日韩影视在线观看| 欧美极品少妇xxxxⅹ免费视频| 韩国国内大量揄拍精品视频| 日韩在线免费视频| 亚洲第一二三四五区| 美女少妇精品视频| 欧美日韩亚洲一区二| 久久久国产影院| 久久91超碰青草是什么| 欧美乱大交xxxxx| 懂色av中文一区二区三区天美| 疯狂做受xxxx高潮欧美日本| 4k岛国日韩精品**专区| 日韩一区二区精品视频| xx视频.9999.com| 色偷偷综合社区| 日韩av电影免费观看高清| 亚洲精品国产精品国自产观看浪潮| 高清视频欧美一级| 国产午夜精品视频| 日韩精品视频在线免费观看| 日本精品性网站在线观看| 久久久久久久久国产精品| 日本精品一区二区三区在线播放视频| 国产精品视频网站| 国产成人av在线播放| 欧美精品在线免费观看| 最近免费中文字幕视频2019| 国产精品扒开腿做爽爽爽的视频| 国产精品白丝jk喷水视频一区| 亚洲精品永久免费| 国产精品欧美一区二区三区奶水| 精品美女久久久久久免费| 中文字幕免费精品一区| 亚洲欧美日韩一区二区三区在线| 福利视频第一区| 91午夜理伦私人影院| 深夜福利国产精品| 伊是香蕉大人久久| 久久久久久91香蕉国产| 中日韩午夜理伦电影免费| 国产日韩综合一区二区性色av| 欧美午夜视频一区二区| 欧美日韩国产影院| 午夜精品久久久久久99热| 综合网日日天干夜夜久久| 亚洲人线精品午夜| 91国语精品自产拍在线观看性色| 欧美—级a级欧美特级ar全黄| 最近2019年手机中文字幕| 亚洲日本中文字幕免费在线不卡| 亚洲曰本av电影| 国产精品自拍偷拍视频| 欧美成人黑人xx视频免费观看| 国产精品久久久久久久电影| 欧美激情国内偷拍| 欧美日韩国产中文字幕| 91嫩草在线视频| 国产精品精品国产| 欧美人与物videos| 国产精品日韩欧美综合| 国产欧美精品va在线观看| 日韩电影免费在线观看中文字幕| 国产精品一区二区三区在线播放| 日韩精品小视频| 欧美性猛交xxxx乱大交3| 国产精品久久久久久婷婷天堂| 日韩中文字幕网站| 亚洲男人天天操| 亚洲男人天堂2024| 欧美重口另类videos人妖| 美女久久久久久久| 久久精品成人欧美大片古装| 国产99久久精品一区二区| 91中文字幕在线| 国产亚洲精品久久久久动| 亚洲国产成人精品久久久国产成人一区| 中文字幕精品在线| 久久国产天堂福利天堂| 久久亚洲精品网站| 91久久精品一区| 午夜精品久久久久久久99热| 九九热在线精品视频| 亚洲天堂开心观看| 亚洲最大av在线| 国产精品美女在线观看| 欧美一级淫片丝袜脚交| 在线观看免费高清视频97| 美女国内精品自产拍在线播放| 精品中文字幕乱| 国产美女久久久| 欧美成人全部免费| 久久久久久网址| 91av成人在线| 精品久久国产精品| 国产精品久久婷婷六月丁香| 精品久久久在线观看| 国产成人精品在线观看| 国产一区二区丝袜高跟鞋图片| 成人中文字幕+乱码+中文字幕| 日产精品99久久久久久|