Linq помогите с помощью "Contains" - PullRequest
2 голосов
/ 18 марта 2010

Доброе утро всем,

Я пытаюсь использовать «Содержит», чтобы увидеть, находится ли объект в коллекции. Когда я ломаюсь, я вижу, что объект действительно является частью коллекции, однако «Contains», похоже, возвращает false, указывая, что элемент отсутствует в коллекции. Есть идеи, что я делаю не так?

if(HttpContext.Current.Session["AutoPayTypes"] != null)
{
    var autopays = HttpContext.Current.Session["AutoPayTypes"] as List<PaymentTypeInfo>;
    char? coverageProductLine = null;

    if(entityProps.ContainsKey("CoverageProductLine"))
    {
       coverageProductLine = (char?)entityProps["CoverageProductLine"];
    }

    var paymentTypeInfoRepository = new PaymentTypeInfoRepository();
    var payType = paymentTypeInfoRepository.GetPaymentTypeInfo(paymentAdd.PayType,
    coverageProductLine);

    if (autopays != null && payType != null)
        paymentAdd.DaysPaid = autopays.Contains(payType) ? null : paymentAdd.DaysPaid;
}

Если объект отсутствует в коллекции, значение «DaysPaid» должно быть нулевым. Есть идеи?

*** UPDATE PaymentTypeInfo - это стандартный сгенерированный класс LinqToSql. На этом этапе значение Equals или GetHashCode не было переопределено. Вот его источник.

[Table(Name="dbo.S_OptPaymentType")]
public partial class PaymentTypeInfo
{

    private string _PaymentId;

    private string _PaymentCode;

    private System.Nullable<char> _CoverageType;

    private string _ActionCode;

    private System.Nullable<char> _PaymentType;

    private string _BenAction;

    private System.Nullable<char> _BenPremDisFlag;

    private string _APNextToLastAct;

    private string _APLastAct;

    public PaymentTypeInfo()
    {
    }

    [Column(Storage="_PaymentId", DbType="Char(3) NOT NULL", CanBeNull=false)]
    public string PaymentId
    {
        get
        {
            return this._PaymentId;
        }
        set
        {
            if ((this._PaymentId != value))
            {
                this._PaymentId = value;
            }
        }
    }

    [Column(Storage="_PaymentCode", DbType="Char(2) NOT NULL", CanBeNull=false)]
    public string PaymentCode
    {
        get
        {
            return this._PaymentCode;
        }
        set
        {
            if ((this._PaymentCode != value))
            {
                this._PaymentCode = value;
            }
        }
    }

    [Column(Storage="_CoverageType", DbType="Char(1)")]
    public System.Nullable<char> CoverageType
    {
        get
        {
            return this._CoverageType;
        }
        set
        {
            if ((this._CoverageType != value))
            {
                this._CoverageType = value;
            }
        }
    }

    [Column(Storage="_ActionCode", DbType="VarChar(3)")]
    public string ActionCode
    {
        get
        {
            return this._ActionCode;
        }
        set
        {
            if ((this._ActionCode != value))
            {
                this._ActionCode = value;
            }
        }
    }

    [Column(Name="PaymentType", Storage="_PaymentType", DbType="Char(1)")]
    public System.Nullable<char> PaymentType
    {
        get
        {
            return this._PaymentType;
        }
        set
        {
            if ((this._PaymentType != value))
            {
                this._PaymentType = value;
            }
        }
    }

    [Column(Storage="_BenAction", DbType="VarChar(3)")]
    public string BenAction
    {
        get
        {
            return this._BenAction;
        }
        set
        {
            if ((this._BenAction != value))
            {
                this._BenAction = value;
            }
        }
    }

    [Column(Storage="_BenPremDisFlag", DbType="Char(1)")]
    public System.Nullable<char> BenPremDisFlag
    {
        get
        {
            return this._BenPremDisFlag;
        }
        set
        {
            if ((this._BenPremDisFlag != value))
            {
                this._BenPremDisFlag = value;
            }
        }
    }

    [Column(Storage="_APNextToLastAct", DbType="VarChar(3)")]
    public string APNextToLastAct
    {
        get
        {
            return this._APNextToLastAct;
        }
        set
        {
            if ((this._APNextToLastAct != value))
            {
                this._APNextToLastAct = value;
            }
        }
    }

    [Column(Storage="_APLastAct", DbType="VarChar(3)")]
    public string APLastAct
    {
        get
        {
            return this._APLastAct;
        }
        set
        {
            if ((this._APLastAct != value))
            {
                this._APLastAct = value;
            }
        }
    }
}

Спасибо, ~ ck в Сан-Диего

Ответы [ 5 ]

3 голосов
/ 18 марта 2010

РЕДАКТИРОВАТЬ: Как отметил Ахмад, использование вашего условного оператора является неправильным. Однако вам даже не нужно , чтобы использовать условный оператор , так как одна из ветвей приводит к неработоспособности. Просто используйте это:

if (autopays != null && payType != null && !autopays.Contains(payType))
{
    paymentAdd.DaysPaid = null;
}

Оригинальный ответ

Вы ничего не показали о PaymentTypeInfo - он корректно переопределяет Equals и GetHashCode? Если нет, проверка на содержание будет выполняться с использованием идентификатора ссылки, и очень маловероятно, что ссылка в сеансе будет такой же, как ссылка в хранилище.

Либо сделайте PaymentTypeInfo переопределить Equals и GetHashCode, либо передайте соответствующий IEqualityComparer<PaymentTypeInfo> в метод Contains.

(Как упоминает SLaks в комментариях, в этом случае GetHashCode на самом деле не будет вызван - но вы всегда должны переопределять оба Equals и GetHashCode или ни один из них; если вы делаете переопределите их, вы должны делать это последовательно.)

2 голосов
/ 18 марта 2010

Если payType не переопределяет Equals или вы не укажете IEqualityComparer, Contains будет сравниваться по ссылке.

Ваша коллекция, вероятно, содержит другой экземпляр класса, который логически эквивалентен.

1 голос
/ 18 марта 2010

Каждый пост до сих пор имеет действительный балл; в зависимости от используемого типа Contains может быть недостаточно. Я обращаюсь к другой части вашего вопроса, хотя:

Если предмета нет в коллекции «DaysPaid» должен быть нулевым. любой идеи?

Как насчет переключения порядка значений вашего троичного оператора в соответствии с приведенным выше утверждением? Используйте это:

paymentAdd.DaysPaid = autopays.Contains(payType) ? paymentAdd.DaysPaid : null;

Вместо этого:

paymentAdd.DaysPaid = autopays.Contains(payType) ? null : paymentAdd.DaysPaid;

Если оператор оценивается как false, будет использоваться 2-й элемент, поэтому сделайте его null. Структура:

logic statement ? true : false
1 голос
/ 18 марта 2010

Возможно, вы столкнулись с проблемой равенства - Contains () использует метод IEquatable.Equals, поэтому вы можете проверить, чтобы убедиться, что он вернет true для отдельных экземпляров класса PaymentTypeInfo.

0 голосов
/ 18 марта 2010

Можете ли вы опубликовать источник класса PaymentType? Я вполне уверен, что этот тип не обеспечивает семантику, основанную на значениях, поэтому метод Contains вынужден прибегнуть к использованию равенства идентичности (которое не дает желаемых результатов).

Если это так, вас могут заинтересовать статьи, которые я написал по этой теме:

...