简体   繁体   中英

Distinct List of object in C#

I have to distinct list of object but NOT only by ID because sometimes two different objects have same ID. I have class:

public class MessageDTO
{

    public MessageDTO(MessageDTO a)
    {
        this.MsgID = a.MsgID;
        this.Subject = a.Subject;
        this.MessageText = a.MessageText;
        this.ViewedDate = a.ViewedDate;
        this.CreatedDate = a.CreatedDate;
    }

    public int? MsgID { get; set; }
    public string Subject { get; set; }
    public string MessageText { get; set; }
    public System.DateTime? ViewedDate { get; set; }
    public System.DateTime? CreatedDate { get; set; }
}

How I can distinct list of:

List<MessageDTO> example;

Thanks

Use LINQ.

public class MessageDTOEqualityComparer : EqualityComparer<MessageDTO>
{
    public bool Equals(MessageDTO a, MessageDTO b)
    {
        // your logic, which checks each messages properties for whatever
        // grounds you need to deem them "equal." In your case, it sounds like
        // this will just be a matter of iterating through each property with an
        // if-not-equal-return-false block, then returning true at the end
    }

    public int GetHashCode(MessageDTO message)
    {
        // your logic, I'd probably just return the message ID if you can,
        // assuming that doesn't overlap too much and that it does
        // have to be equal on the two
    }
}

Then

return nonDistinct.Distinct(new MessageDTOEqualityComparer());

You can also avoid the need for an extra class by overriding object.Equals(object) and object.GetHashCode() and calling the empty overload of nonDistinct.Distinct() . Make sure you recognize the implications of this decision, though: for instance, those will then become the equality-testing functions in all non-explicit scopes of their use. This might be perfect and exactly what you need, or it could lead to some unexpected consequences. Just make sure you know what you're getting into.

I you want to use other properties, you should implement IEqualityComparer interface. More on: msdn

class MsgComparer : IEqualityComparer<MessageDTO>
{
    public bool Equals(MessageDTO x, MessageDTO Oy)
    {
    }

    // If Equals() returns true for a pair of objects 
    // then GetHashCode() must return the same value for these objects.

    public int GetHashCode(MessageDTO m)
    {
           //it must br overwritten also
    }

}

Then:

example.Distinct(new MsgComparer());

You could also overwrite Equals in MessageDTO class:

class MessageDTO 
{
    // rest of members
    public override bool Equals(object obj) 
    {
        // your stuff. See: http://msdn.microsoft.com/en-us/library/ms173147%28v=vs.80%29.aspx
    }
    public override int GetHashCode()
    {
    }
}

Then it's enough:

example.Distinct();

You could use the extension method DistinctBy from the MoreLinq library:

string[] source = { "first", "second", "third", "fourth", "fifth" };
var distinct = source.DistinctBy(word => word.Length);

See here :

I recommend you using solution of @Matthew Haugen

In case you don't want to create a new class for that, there is a way to use LINQ by grouping you list by distinct field(s) then select the first item on this group. For example:

example.(e => new { e.MsgID, e.Subject }).Select(grp => grp.FirstOrDefault());

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM