Linq help using "Contains"
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开发者_如何学JAVA?
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
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.)
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.
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.
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
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:
- All types are not compared equally
- All types are not compared equally (part 2)
精彩评论