problem related to overloading == operator

C

Constantine

Hi, I have developed one class called CProductInfo providing == and !=
operator features. I have one problem.

When I use this class in my program, say

CProductInfo product = null;

and later, when i check for emptiness,

if (product==null)

it returns false as if the product instance is not empty.

I tried various ways to eliminate this run-time error, but it just does
not happen. Also I don't think there is use full tips on net for this.

Can someone help?

Thanks in advance - Rhonald

<<<< THE SOURCE CODE FOR CProductInfo IS BELOW >>>>>




using System;
using System.Data;
using System.Data.SqlClient;
using MyDataLibrary;

namespace ProductManager2006
{
/// <summary>
/// Summary description for CProductInfo.
/// </summary>
public class CProductInfo:ConnectionManager
{
internal long m_AutoIndex = 0;
internal string m_SerialNumber = "";
public string Title = "";
private DateTime m_DateReference = DateTime.Now;
private DateTime m_DateStart = DateTime.Now, m_DateFinish =
DateTime.Now;
public ProductType Type = ProductType.CustomizedProduct;
public string Version = "", Build = "", Explanation = "";
public string Notes = "", Features = "", SystemRequirements = "",
PreRequisites = "";
public bool Status = true;
private bool m_IsDateStartAvailable = false, m_IsDateFinishAvailable
= false;

public CProductInfo()
{
//
// TODO: Add constructor logic here
//
}

public CProductInfo(string productId)
{
Open(productId);
}

public CProductInfo(DataRow dr)
{
if (dr!=null)
{
m_AutoIndex = DataConverter.ToLong(dr["auto_index"].ToString());
m_SerialNumber = dr["pk_product_id"].ToString();
m_DateReference =
Convert.ToDateTime(dr["date_reference"].ToString());
Title = dr["title"].ToString();

if (!dr.IsNull(4)) DateStart =
Convert.ToDateTime(dr["date_start"].ToString());
if (!dr.IsNull(5)) DateFinish =
Convert.ToDateTime(dr["date_finish"].ToString());

Type =
DataConverter.ToBoolean(dr["product_type"].ToString())?ProductType.GeneralizedProduct:productType.CustomizedProduct;

Version = dr["version"].ToString();
Build = dr["build"].ToString();
Notes = dr["notes"].ToString();
Features = dr["features"].ToString();
SystemRequirements = dr["system_requirements"].ToString();
PreRequisites = dr["prerequisites"].ToString();
Status = DataConverter.ToBoolean(dr["status"].ToString());
}
}

private string _NewID
{
get
{
SqlCommand cmdSql = new SqlCommand("select isnull(max(auto_index),
0) as counter from mstrproducts", Connection);

try
{
OpenConnection();

SqlDataReader dr = cmdSql.ExecuteReader();

if (dr.Read())
{
return
((DataConverter.ToInteger(dr["counter"].ToString())+1).ToString("00000"));
}
}
catch(Exception ex)
{
Console.WriteLine(ex.ToString());

return null;
}
finally
{
CloseConnection();
}

return null;
}
}

public string SerialNumber
{
get
{
return m_SerialNumber;
}
}

public DateTime DateReference
{
get
{
return m_DateReference;
}
}

public DateTime DateStart
{
get
{
return m_DateStart;
}
set
{
m_DateStart = value;

m_IsDateStartAvailable = true;
}
}

public DateTime DateFinish
{
get
{
return m_DateFinish;
}
set
{
m_DateFinish = value;

m_IsDateFinishAvailable = true;
}
}

public bool IsDateStartAvailable
{
get
{
return m_IsDateStartAvailable;
}
}

public bool IsDateFinishAvailable
{
get
{
return m_IsDateFinishAvailable;
}
}

public bool IsCustomBuilt
{
get
{
return Type == ProductType.CustomizedProduct?true:false;
}
}

public bool IsGeneralBuilt
{
get
{
return Type == ProductType.GeneralizedProduct?true:false;
}
}

public bool Open(string id)
{
SqlCommand cmdSql = new SqlCommand("select * from mstrproducts where
pk_product_id='"+id+"'", Connection);

try
{
OpenConnection();

SqlDataReader dr = cmdSql.ExecuteReader();

if (dr.Read())
{
m_AutoIndex = DataConverter.ToLong(dr["auto_index"].ToString());
m_SerialNumber = dr["pk_product_id"].ToString();
m_DateReference =
Convert.ToDateTime(dr["date_reference"].ToString());
Title = dr["title"].ToString();

if (!dr.IsDBNull(4))
{
DateStart = Convert.ToDateTime(dr["date_start"].ToString());

m_IsDateStartAvailable = true;
}
else
m_IsDateStartAvailable = false;

if (!dr.IsDBNull(5))
{
DateFinish = Convert.ToDateTime(dr["date_finish"].ToString());

m_IsDateFinishAvailable = true;
}
else
m_IsDateFinishAvailable = false;

Type =
DataConverter.ToBoolean(dr["product_type"].ToString())?ProductType.GeneralizedProduct:productType.CustomizedProduct;

Version = dr["version"].ToString();
Build = dr["build"].ToString();
Notes = dr["notes"].ToString();
Features = dr["features"].ToString();
SystemRequirements = dr["system_requirements"].ToString();
PreRequisites = dr["prerequisites"].ToString();
Status = DataConverter.ToBoolean(dr["status"].ToString());
}
}
catch(Exception ex)
{
Console.WriteLine(ex.ToString());

return false;
}
finally
{
CloseConnection();
}

return true;
}

internal bool Save()
{
SqlCommand cmdSql = new SqlCommand("RegisterProducts", Connection);
cmdSql.CommandType = CommandType.StoredProcedure;

if (m_SerialNumber.Trim().Length<=0) m_SerialNumber = _NewID;

cmdSql.Parameters.Add(new SqlParameter("@product_id",
SqlDbType.VarChar, 10)).Value = SerialNumber;
cmdSql.Parameters.Add(new SqlParameter("@date_reference",
SqlDbType.SmallDateTime)).Value =
Convert.ToDateTime(DateReference.ToShortDateString());
cmdSql.Parameters.Add(new SqlParameter("@title", SqlDbType.VarChar,
150)).Value = Title;

if (IsDateStartAvailable) cmdSql.Parameters.Add(new
SqlParameter("@date_start", SqlDbType.SmallDateTime)).Value =
DateStart;
if (IsDateFinishAvailable) cmdSql.Parameters.Add(new
SqlParameter("@date_finish", SqlDbType.SmallDateTime)).Value =
DateFinish;

cmdSql.Parameters.Add(new SqlParameter("@product_type",
SqlDbType.Bit)).Value = (Type == ProductType.GeneralizedProduct?0:1);
cmdSql.Parameters.Add(new SqlParameter("@version",
SqlDbType.VarChar, 15)).Value = Version;
cmdSql.Parameters.Add(new SqlParameter("@build", SqlDbType.VarChar,
15)).Value = Build;
cmdSql.Parameters.Add(new SqlParameter("@notes", SqlDbType.NVarChar,
500)).Value = Notes;
cmdSql.Parameters.Add(new SqlParameter("@features",
SqlDbType.NVarChar, 500)).Value = Features;
cmdSql.Parameters.Add(new SqlParameter("@system_requirements",
SqlDbType.NVarChar, 500)).Value = SystemRequirements;
cmdSql.Parameters.Add(new SqlParameter("@prerequisites",
SqlDbType.NVarChar, 500)).Value = PreRequisites;
cmdSql.Parameters.Add(new SqlParameter("@status",
SqlDbType.Bit)).Value = (Status?1:0);

try
{
OpenConnection();

cmdSql.ExecuteNonQuery();
}
catch(Exception ex)
{
Console.WriteLine(ex.ToString());

return false;
}

return true;
}

internal bool Delete()
{
return false;
}

public static bool operator == (CProductInfo product1, CProductInfo
product2)
{
return product1.Equals(product2);
}

public static bool operator != (CProductInfo product1, CProductInfo
product2)
{
return (!product1.Equals(product2));
}

public override bool Equals(object obj)
{
if (!(obj is CProductInfo)) return false;
return this==(CProductInfo)obj;
}

public override int GetHashCode()
{
return base.GetHashCode ();
}

public override string ToString()
{
return base.ToString ();
}

}
}
 
J

Jon Skeet [C# MVP]

Constantine said:
Hi, I have developed one class called CProductInfo providing == and !=
operator features. I have one problem.

When I use this class in my program, say

CProductInfo product = null;

and later, when i check for emptiness,

if (product==null)

it returns false as if the product instance is not empty.

I tried various ways to eliminate this run-time error, but it just does
not happen. Also I don't think there is use full tips on net for this.

It's not clear what runtime error you're talking about. However,
general rules:

o Check whether you've been passed null (using object.ReferenceEquals)
in the Equals method.
o Use object.ReferenceEquals to check against a null reference for both
parameters in your == and != overloads, in order to avoid
NullReferenceExceptions.

Jon
 
I

Ignacio Machin \( .NET/ C# MVP \)

Hi,

Next time just post the relevant code.


No idea what error are you talking, unless that you have something like:

CProductInfo product = null;


if (product==null) product = new CProductInfo ();

product.SomeAction();


Of course as you are seeing the if is always false and therefore the
instance may never be initialized.


**** update ****
ok, I think I know where the error is, it's in :

public static bool operator == (CProductInfo product1, CProductInfo
product2)
{
return product1.Equals(product2);
}

you are presuming that the first argument of "==" is an initialized instance
when it's not there you will get a NullReference Exception.


**** end of update ****

See Jon's comments to how to do it.

IMO it's not a very good idea overload == , the operator has a VERY CLEAR
meaning of comparing references, not members's values of those instances.

WARNING:

Also you may be getting in an infinite recursion, you call Equals from "=="
and inside Equals you again call "=="
 
T

Tom Spink

Constantine said:
Hi, I have developed one class called CProductInfo providing == and !=
operator features. I have one problem.

When I use this class in my program, say

CProductInfo product = null;

and later, when i check for emptiness,

if (product==null)

it returns false as if the product instance is not empty.

I tried various ways to eliminate this run-time error, but it just does
not happen. Also I don't think there is use full tips on net for this.

Can someone help?

Thanks in advance - Rhonald
<snippedy-doo-dah>

Hi Rhonald,

You have a slight bug in your code, which I'm guessing hasn't surfaced
because you have a bit of exception handling somewhere.

You've got to make sure 'product1' in your operator overloads isn't null,
before you call the 'Equals' method.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top