C# DistinctBy与Distinct的区别

你想了解在C[#中对反序列化得到的](javascript:😉Vehicle列表使用DistinctByDistinct方法的核心区别,尤其是在按字段去重场景下两者的行为差异。

图片

一、核心区别详解

首先需要明确:这两个方法都是LINQ中用于去重的方法,但去重的判断逻辑和使用方式完全不同,结合你的代码场景逐一说明:

1. 先补全必要的Vehicle类定义

你的代码中用到了Vehicle类,但未展示定义,先补充完整(保证代码可运行):

using DistinctDemo;using Newtonsoft.Json;using System.Collections.Generic;using System.Linq;// 补全Vehicle类定义namespaceDistinctDemo{public class Vehicle    {        [JsonProperty("number")]public string Number { get; set; }        [JsonProperty("vehicleNo")]public string VehicleNo { get; set; }        [JsonProperty("statusEnum")]public int StatusEnum { get; set; }        [JsonProperty("status")]public string Status { get; set; }        [JsonProperty("createdDateTime")]public DateTime CreatedDateTime { get; set; }    }}Console.WriteLine("Hello, World!");var json = $"
[
        {
            "number": "202601210010",
            "vehicleNo": "鲁H232H0",
            "statusEnum": 1,
            "status": "厂外",
            "createdDateTime": "2026-01-21T11:42:56.060242"
        },
        {
            "number": "202601210010",
            "vehicleNo": "鲁H232H0",
            "statusEnum": 1,
            "status": "厂外",
            "createdDateTime": "2026-01-21T11:42:56.060242"
        },
        {
            "number": "202601210010",
            "vehicleNo": "鲁H232H0",
            "statusEnum": 1,
            "status": "厂外",
            "createdDateTime": "2026-01-21T11:42:56.060242"
        },
        {
            "number": "202601210010",
            "vehicleNo": "鲁H232H0",
            "statusEnum": 1,
            "status": "厂外",
            "createdDateTime": "2026-01-21T11:42:56.060242"
        },
        {
            "number": "202601210010",
            "vehicleNo": "鲁H232H0",
            "statusEnum": 1,
            "status": "厂外",
            "createdDateTime": "2026-01-21T11:42:56.060242"
        },
        {
            "number": "202601210011",
            "vehicleNo": "鄂B5B818",
            "statusEnum": 1,
            "status": "厂外",
            "createdDateTime": "2026-01-21T12:48:24.246919"
        }
    ]
";var vehicles = JsonConvert.DeserializeObject<List<Vehicle>>(json);// 按Number字段去重var v2 = vehicles.DistinctBy(r => r.Number).ToList();// 默认按对象实例去重(无效果)var v3 = vehicles.Distinct().ToList();Console.WriteLine($"原列表数量:{vehicles.Count}"); // 输出 6Console.WriteLine($"DistinctBy去重后数量:{v2.Count}"); // 输出 2(202601210010 和 202601210011)Console.WriteLine($"Distinct去重后数量:{v3.Count}"); // 输出 6(无去重效果)

2. Distinct() 方法

  • 核心逻辑

    :判断整个对象是否完全相等,默认规则:

  • 对于值类型(如int、string):按“值”相等判断;

  • 对于自定义引用类型(如Vehicle):按“引用地址”相等判断(即只有同一个对象实例才会被判定为重复)。

  • 你的场景表现

    :你反序列化得到的6个Vehicle对象都是独立的实例(即使字段值完全相同),所以Distinct()会认为所有对象都不重复,最终返回6个对象,无去重效果

  • 要让Distinct按字段去重

    :必须自定义相等逻辑(重写EqualsGetHashCode,或传入IEqualityComparer<Vehicle>),示例:```
    // 自定义比较器:按Number字段判断相等
    public class VehicleNumberComparer : IEqualityComparer
    {
    public bool Equals(Vehicle x, Vehicle y)
    {
    if (x == null || y == null) returnfalse;
    return x.Number == y.Number;
        }

    public int GetHashCode(Vehicle obj)
    {
    return obj.Number.GetHashCode();
        }
    }

    // 使用自定义比较器的Distinct
    var v4 = vehicles.Distinct(new VehicleNumberComparer()).ToList();
    Console.WriteLine($"自定义Distinct去重后数量:{v4.Count}"); // 输出 2

    
    
    

3. DistinctBy<TKey>() 方法

  • 核心逻辑

    :.NET 6+ 新增方法,允许指定一个键选择器(Key Selector),按“指定字段/属性的值”去重,无需修改Vehicle类或自定义比较器。

  • 你的场景表现

    DistinctBy(r => r.Number) 会提取每个VehicleNumber字段,只要Number值相同就判定为重复,最终只保留每个Number的第一个对象,所以返回2个对象(202601210010 和 202601210011)。

  • 灵活性

    :可按任意字段/组合字段去重,比如按Number + VehicleNo组合去重:```
    var v5 = vehicles.DistinctBy(r => $"{r.Number}_{r.VehicleNo}").ToList();

    
    
    

二、关键差异对比表

|
特性

|

Distinct()

|

DistinctBy()

|
| --- | --- | --- |
|

去重依据

|

整个对象的相等性(默认按引用)

|

指定字段/属性的键值

|
|

.NET 版本要求

|

所有版本

|

.NET 6+

|
|

使用复杂度

|

需自定义比较器(按字段去重时)

|

直接指定键选择器,简洁易用

|
|

你的代码执行结果

|

返回6个对象(无去重)

|

返回2个对象(按Number去重)

|

总结

  1. Distinct()

    是“对象级去重”,默认比较引用,按字段去重需自定义相等逻辑,适配所有.NET版本;

  2. DistinctBy()

    是“字段级去重”,.NET 6+ 新增,通过键选择器直接指定去重字段,无需修改实体类,使用更简洁;

  3. 在你的场景中,要按Number去重,DistinctBy(r => r.Number) 是最优选择(无需额外代码),而Distinct() 默认无效果,需自定义比较器才能实现相同效果。

posted @ 2026-01-26 17:02  东百牧码人  阅读(2)  评论(0)    收藏  举报