views:

208

answers:

5

Good Morning All,

I'm trying to use "Contains" to see if an object is within the collection. When I break I can see that the object is indeed part of the collection however "Contains" seems to be returning false indicating the item is not in the collection. Any idea what I'm doing wrong?

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;
}

If the object is not in the collection the "DaysPaid" needs to be null. Any ideas?

***UPDATE PaymentTypeInfo is a standard LinqToSql generated class. Equals nor GetHashCode has been overridden at this point. Here is it's source.

[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;
            }
        }
    }
}

Thanks, ~ck in San Diego

+1  A: 

It's possible you're running into an equality issue - Contains() uses the IEquatable.Equals method, so you might check to make sure that that's going to return true for separate instances of the PaymentTypeInfo class.

Adam V
+3  A: 

EDIT: As Ahmad pointed out, your conditional operator usage is incorrect. However, you don't even need to use the conditional operator here, as one of the branches results in a no-op. Just use this:

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

Original answer

You haven't shown any thing about PaymentTypeInfo - does it override Equals and GetHashCode appropriately? If not, the containment check will be performed using reference identity, and it's very unlikely that the reference in the session is the same as the reference in the repository.

Either make PaymentTypeInfo override Equals and GetHashCode, or pass an appropriate IEqualityComparer<PaymentTypeInfo> into the Contains method.

(As SLaks mentions in the comments, in this case GetHashCode won't actually get called - but you should always override both Equals and GetHashCode or neither of them; if you do override them, you should do so in a consistent manner.)

Jon Skeet
`Contains` doesn't call `GetHashCode`. (Although many other methods do)
SLaks
If you override Equals(), it's recommended you override GetHashCode(). The compiler throws a warning at you if you don't.
Adam V
I am certainly not suggesting that you override `Equals` without `GetHashCode`. (Although the warning is from FxCop, not the compiler)
SLaks
@SLaks: I'll clarify that in the post.
Jon Skeet
This seemed to do the trick. I didn't override anything and it seems to behave correctly in both situations
Hcabnettek
+1  A: 

Unless payType overrides Equals or you specify an IEqualityComparer, Contains will compare by reference.

Your collection probably contains a different instance of the class which is logically equivalent.

SLaks
A: 

Can you post the source of the PaymentType class? I am fairly certain that this type does not provided value-based semantics so the Contains method is forced to resort to using identity equality (which is not giving you the results you want).

If this is the case you may be interested in these articles I wrote on this topic:

Andrew Hare
+1  A: 

Every post so far has a valid point; depending on the type being used Contains may not suffice. I am addressing a different part of your question though:

If the object is not in the collection the "DaysPaid" needs to be null. Any ideas?

How about switching the order of your ternary operator values to match the above statement? Use this:

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

Instead of this:

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

If the statement evaluates to false the 2nd item will be used, so make it null. The structure is:

logic statement ? true : false
Ahmad Mageed
Doh - I was fixated on the Contains part :)
Jon Skeet
@Ahmad: In fact, looking at that makes it clear that the conditional operator isn't required at all. See my updated answer.
Jon Skeet
@Jon: agreed, that is cleaner :)
Ahmad Mageed