C# Can';无法使用LINQ从列表中获取不同的项

C# Can';无法使用LINQ从列表中获取不同的项,c#,linq,anonymous-class,C#,Linq,Anonymous Class,我在C#上了下面的课,我试图找到一个不同的项目列表。 该列表有24个元素 public enum DbObjectType { Unknown, Procedure, Function, View } public class DbObject { public string DatabaseName { get; set; } public string SchemaName { get; set; } public string Ob

我在C#上了下面的课,我试图找到一个不同的项目列表。 该列表有24个元素

public enum DbObjectType
{
    Unknown,
    Procedure,
    Function,
    View
}

public class DbObject
{
    public string DatabaseName { get; set; }
    public string SchemaName { get; set; }
    public string ObjectName { get; set; }
    public DbObjectType ObjectType { get; set; }
}
我有两种方法,希望得到相同的结果,但我没有

第一个表达式返回相同的列表(包括重复项)

lst1将有24个项目

但是这个函数返回了期望的结果

var lst2 = from c in DependantObject
          group c by new 
          {
              DatabaseName = c.DatabaseName,
              SchemaName = c.SchemaName,
              ObjectName = c.ObjectName,
              ObjectType = c.ObjectType
          } into grp
          select grp.First();
lst2将有10个项目

唯一的区别是第二个表达式是匿名的,但第一个表达式是类型化的

我很想了解这种行为

谢谢大家!

我相信我的问题与上述问题并不相同,因为: 我在这里问的不是如何得到不同的列表。我在问为什么键入的数据和匿名数据返回不同的结果。

Linq的
Distinct()
方法需要重写
GetHashCode
Equals

C#的异常类型(
new{Name=value}
语法)创建的类确实覆盖了这些方法,但您自己的
DbObject
类型却没有

您还可以创建自定义
IEqualityComparer
类型。查看
structuralComparer.StructuralEqualityComparer

备选案文1:

public class DbObject : IEquatable<DbObject> {

    public override Int32 GetHashCode() {

        // See https://stackoverflow.com/questions/263400/what-is-the-best-algorithm-for-an-overridden-system-object-gethashcode

        unchecked
        {
            int hash = 17;
            hash = hash * 23 + this.DatabaseName.GetHashCode();
            hash = hash * 23 + this.SchemaName.GetHashCode();
            hash = hash * 23 + this.ObjectName.GetHashCode();
            hash = hash * 23 + this.ObjectType.GetHashCode();
            return hash;
        }
    }

    public override Boolean Equals(Object other) {

        return this.Equals( other as DbObject );    
    }

    public Boolean Equals(DbObject other) {

        if( other == null ) return false;
        return
            this.DatabaseName.Equals( other.DatabaseName ) &&
            this.SchemaName.Equals( other.SchemaName) &&
            this.ObjectName.Equals( other.ObjectName ) &&
            this.ObjectType.Equals( other.ObjectType);
    }
}
备选案文2用途:

var query = this.DependantObject
    .GroupBy( c => new DbObject() {
        DatabaseName = c.DatabaseName,
        SchemaName   = c.SchemaName,
        ObjectName   = c.ObjectName,
        ObjectType   = c.ObjectType
    } )
    .First();
使用
GroupBy
可能不太理想,您可以直接使用Linq
Distinct

var query = this.DependantObject
    .Select( c => new DbObject() {
        DatabaseName = c.DatabaseName,
        SchemaName   = c.SchemaName,
        ObjectName   = c.ObjectName,
        ObjectType   = c.ObjectType
    } )
    .Distinct()
    .First();
Linq的
Distinct()
方法需要重写
GetHashCode
Equals

C#的异常类型(
new{Name=value}
语法)创建的类确实覆盖了这些方法,但您自己的
DbObject
类型却没有

您还可以创建自定义
IEqualityComparer
类型。查看
structuralComparer.StructuralEqualityComparer

备选案文1:

public class DbObject : IEquatable<DbObject> {

    public override Int32 GetHashCode() {

        // See https://stackoverflow.com/questions/263400/what-is-the-best-algorithm-for-an-overridden-system-object-gethashcode

        unchecked
        {
            int hash = 17;
            hash = hash * 23 + this.DatabaseName.GetHashCode();
            hash = hash * 23 + this.SchemaName.GetHashCode();
            hash = hash * 23 + this.ObjectName.GetHashCode();
            hash = hash * 23 + this.ObjectType.GetHashCode();
            return hash;
        }
    }

    public override Boolean Equals(Object other) {

        return this.Equals( other as DbObject );    
    }

    public Boolean Equals(DbObject other) {

        if( other == null ) return false;
        return
            this.DatabaseName.Equals( other.DatabaseName ) &&
            this.SchemaName.Equals( other.SchemaName) &&
            this.ObjectName.Equals( other.ObjectName ) &&
            this.ObjectType.Equals( other.ObjectType);
    }
}
备选案文2用途:

var query = this.DependantObject
    .GroupBy( c => new DbObject() {
        DatabaseName = c.DatabaseName,
        SchemaName   = c.SchemaName,
        ObjectName   = c.ObjectName,
        ObjectType   = c.ObjectType
    } )
    .First();
使用
GroupBy
可能不太理想,您可以直接使用Linq
Distinct

var query = this.DependantObject
    .Select( c => new DbObject() {
        DatabaseName = c.DatabaseName,
        SchemaName   = c.SchemaName,
        ObjectName   = c.ObjectName,
        ObjectType   = c.ObjectType
    } )
    .Distinct()
    .First();

因此,您可以说,当使用匿名时,编译器会比较属性,但当使用类型化数据时,它会查看GetHashCode和Equals方法?@FLICKER-编译器不会知道类中的equality是由什么构成的。一种方法是实现
IEqualityComparer
并使用Distinct()重载,这是我以前做过的方法。我最近在这里回答了一个类似的问题-代码在VB.NET中,但概念应该是相同的。@Dai,这是新的,我从未尝试在匿名类型上使用distinct,所以不知道它们是如何工作的。所以,你说当使用匿名时,编译器会比较属性,但当使用类型化数据时,它将研究GetHashCode和Equals方法?@FLICKER-编译器将不知道类中的equality是由什么构成的。一种方法是实现
IEqualityComparer
并使用Distinct()重载,这是我以前做过的方法。我最近在这里回答了一个类似的问题-代码在VB.NET中,但概念应该是相同的。@Dai,这是新的,我从未尝试在匿名类型上使用distinct,所以不知道它们是如何工作的。