Создание отдельного списка настраиваемого типа в С#

Я получаю список типов сущностей en entity и хочу возвращать только отдельные значения из списка. Я использую следующий подход, однако это не является уникальным списком. Любые предложения?

Параметр: List<Flag> flags

List<Flag> distinctFlags = flags.Distinct().ToList();

Значения флага следующие: ID, Flag, FlagValue. Могу ли я использовать linq в этом экземпляре?

Спасибо.

Ответ 1

Предполагая, что Flag является одной из ваших моделей сущностей, вы можете использовать partial class и переопределить Equals и GetHashCode. Это также предполагает, что у вас есть свойство Id на вашем Flag class, которое однозначно идентифицирует его.

//this namespace MUST match the namespace of your entity model.
namespace Your.Entity.Model.Namespace
{
    public partial class Flag
    {
        public override bool Equals(object obj)
        {
            var item = obj as Flag;

            if (item == null)
            {
                return false;
            }

            return this.Id.Equals(item.Id);
        }

        public override int GetHashCode()
        {
            return this.Id.GetHashCode();
        }
    }
}

Использование будет выглядеть следующим образом

List<Flag> distinctFlags = allFlags.Distinct().ToList();

Ответ 2

Вероятно, flags - это список ссылочного типа, а отдельный не работает так, как вы ожидаете! Это потому, что Distinct() работает не по значению флага в списке, а по его ссылкам на память (все они разные).

Вам нужно написать класс сравнения, который учит отличать, как сравнивать равный флаг. Предположим, что у вас есть этот класс флагов:

public class flag
{ 
    public string Name { get; set; }
    public string Code { get; set; }
}

вам следует создать класс сравнения следующим образом:

class FlagComparer : IEqualityComparer<flag>
{
    // Products are equal if their names and product numbers are equal.
    public bool Equals(flag x, flag y)
    {

        //Check whether the compared objects reference the same data.
        if (Object.ReferenceEquals(x, y)) return true;

        //Check whether any of the compared objects is null.
        if (Object.ReferenceEquals(x, null) || Object.ReferenceEquals(y, null))
            return false;

        //Check whether the products' properties are equal.
        return x.Code == y.Code && x.Name == y.Name;
    }
}

и вызов вашего заявления:

List distinctFlags = flags.Distinct(new FlagComparer ()).ToList();

Таким образом, метод Distinct точно знает, как сравнивать equal flag istance.

UPDATE

На основании вашего комментария, если вы хотите следовать моему предложению, вы должны написать базу сравнения следующим образом:

class FlagComparer : IEqualityComparer<flag>
    {
        // Products are equal if their names and product numbers are equal.
        public bool Equals(flag x, flag y)
        {

            //Check whether the compared objects reference the same data.
            if (Object.ReferenceEquals(x, y)) return true;

            //Check whether any of the compared objects is null.
            if (Object.ReferenceEquals(x, null) || Object.ReferenceEquals(y, null))
                return false;

            //Check whether the products' properties are equal.
            return x.HostID == y.HostID && x.RuleID == y.RuleID && x.Flag == y.Flag && x.FlagValue == y.FlagValue;
        }
    }

Конечно, каждое свойство должно быть типом значения.

Взгляните сюда, чтобы уточнить: