Compare two instance of a class

  • Thread starter Thread starter bengamin
  • Start date Start date
B

bengamin

Hi,

I have a C# class and two instance of the class;

the class have some property.

I want to compare the property value of the two instance

How should i do? override == ? use delegate ?

I am sorry ,my english was poor.
 
bengamin said:
Hi,

I have a C# class and two instance of the class;

the class have some property.

I want to compare the property value of the two instance

How should i do? override == ? use delegate ?

I am sorry ,my english was poor.

I have been trying to find out the same thing.
From what I can see, if you overrride == in your class then you should
also override Equals, != and GetHashCode.
So that they all exhibit the same behaviour.

Since I might want to test for reference equality in one case and say
check the ID property in another case I would like to override == to
check for ID equality but from what I understand thats not a good idea
as other languages (VB) does not have this operator.

You might want to define an interface that would do a property check on
both instances to determine whether they are equal.

Sorry I cannot be more decisive, I would like to see others views :)

Cheers
 
Recommended practice is that operator "==" and method
"Object.Equals(object)" should behave the same.
If you override Equal you should also override GetHashCode.

You need to bear in mind whether or not you will ever need to compare 2
references (which is the default behaviour) i.e. that refer to the same
instance.

In most cases I think it is better to implement a specific method to compare
reference type instances - value comparison is often a business/application
specific function, and it may be misleading to some developers if you
override default language functionality.

Here's a useful article on MSDN:
http://msdn.microsoft.com/library/d...nref/html/cpconimplementingequalsoperator.asp

Richard.
 
Sorry but I've gotten curious because of these replies. I don't seem to
understand the question maybe?

I thought what he meant was just that if you have let's say, the following
class:

class A
{
private int _i;

public int i
{
get
{ return this._i; }
set
{ this._i = value; }
}
}

and A a1 = new A(); A a2 = new A();
then a1.i == a2.i would simply return true if they have the same value? That
was the question right? Why would you need to overload the operator for
that?
 
Hi,

Good practise is to implement "IComparable" interface.

int CompareTo(Object obj)
- it should return zero if "obj" is equal to base object.

Then you have to (easily) override the "Equals()", as follow:

public override bool Equals(Object obj) {
return (this.CompareTo(obj)==0);
}

Cheers

Marcin
 
Hi Razzie,

Don't you think that there can be more properties than
one or two?

e.g.
// A Person class, that have: FirstName, LastName, Age, Gender.
Person person1=new Person();
Person person2=new Person();

if( person1.FirstName==person2.FirstName
&& person1.LastName==person2.LastName
&& person1.Age==person2.Age
&& person1.Gender==person2.Gender ) {
//...
}

It looks very complicated. Don't you think?

Regards

Marcin
 
Hi,

== overloading should be the way to go, now according to MSDN you also need
to overload != but nothing more, it saids nothing about Equals or
GetHashCode.

If you overload the default meaning of the == operator you will not longer
compare references , if you want do so you could do it casting both operands
to Object, like this:
(object)instance1 == (object) instance2
It should work.

Cheers,
 
ah well, he wrote value and not values... :)

Marcin Grzêbski said:
Hi Razzie,

Don't you think that there can be more properties than
one or two?

e.g.
// A Person class, that have: FirstName, LastName, Age, Gender.
Person person1=new Person();
Person person2=new Person();

if( person1.FirstName==person2.FirstName
&& person1.LastName==person2.LastName
&& person1.Age==person2.Age
&& person1.Gender==person2.Gender ) {
//...
}

It looks very complicated. Don't you think?

Regards

Marcin
 
Yes, question just as you describe

since i want to build a command function for all class,and i don't know how
to do,so i thought about overload "=="
 
thank you very much!

The Last Gunslinger said:
I have been trying to find out the same thing.
From what I can see, if you overrride == in your class then you should
also override Equals, != and GetHashCode.
So that they all exhibit the same behaviour.

Since I might want to test for reference equality in one case and say
check the ID property in another case I would like to override == to
check for ID equality but from what I understand thats not a good idea
as other languages (VB) does not have this operator.

You might want to define an interface that would do a property check on
both instances to determine whether they are equal.

Sorry I cannot be more decisive, I would like to see others views :)

Cheers
 
Unless you want complete value semantics (like the string class has), you
shouldn't override the == operator.

Can't you just have a special equality method on the class:

class X
{
private int myProperty;
public int MyProperty { get { return this.myProperty } }

bool IsValueEqualTo(X otherX)
{
return this.MyProperty == otherX.MyProperty;
}
}

Christian
 
Hi bengamin,

Here is your sample:

public class Person
: IComparable
{
private int age;
private string lastName;
private string firstName;
private bool maleGender;

public int CompareTo(object obj) {
Person secondPerson=obj as Person;
if( secondPerson==null ) {
throw new ArgumentNullException("obj");
}
int result;
result=(age-obj.age);
if( result!=0 ) {
return result;
}
result=lastName.CompareTo(obj.lastName);
if( result!=0 ) {
return result;
}
result=firstName.CompareTo(obj.firstName);
if( result!=0 ) {
return result;
}
result=maleGender.CompareTo(obj.maleGender);
return result;
}

}

Cheers!

Marcin
 
Hi,Marcin

Thany you !

The example you give have a presupposition/precondition that we must know
the properties ,but the fact is we don't know the properties.

Today i found a new way to implement the function
This is the example code:

Class1 a = new Class1();
Class1 b = new Class1();
XmlSerializer formatter = new XmlSerializer(typeof(Class1));
Byte[] buff = new Byte[1024];
Stream stream = new MemoryStream(buff);
formatter.Serialize(stream, a);
Byte[] buff1 = new Byte[1024];
Stream stream1 = new MemoryStream(buff1);
formatter.Serialize(stream1, b);

for(int i = 0 ; i < buff.Length ; i ++ )
{
if (buff != buff1)
{
label1.Text = "false";
return;
}
}
label1.Text = "true";


But there is some problem :
1, HashTable can not be xmlserializer;
2, The sample class i used for example is ok ,but when turn to the class of
our business layer,
there come an error when step into "Stream stream = new
MemoryStream(buff);"


I don't know why ,is somebody can give me some help?

Thank you!
 
If you really want to do byte comparison, you would be better off using
BinaryFormatter.
(Note your XmlSerializer only takes the public properties). See Compare1
below.

Another good solution where you don't know the properties is to use
reflection. See Compare2 below - much simpler.

(sample code for illustration - not tested...)
*************

using System;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using System.Reflection;

namespace ClassLibrary1
{
/// <summary>
/// Summary description for Class1.
/// </summary>
public class Class1
{
int i = 0;
string s = "";
object o = null;

public Class1()
{
}

public static bool Compare1( Class1 c1, Class1 c2 )
{
BinaryFormatter f1 = new BinaryFormatter();
MemoryStream s1 = new MemoryStream();
BinaryFormatter f2 = new BinaryFormatter();
MemoryStream s2 = new MemoryStream();

f1.Serialize(s1,c1);
f2.Serialize(s2,c2);

byte[] buf1 = s1.ToArray();
byte[] buf2 = s2.ToArray();

if (buf1.Length==buf2.Length)
return false;

for (int i=0; i<buf1.Length; i++)
{
if (buf1!=buf2)
return false;
}
}

public static bool Compare2( Class1 c1, Class1 c2 )
{
Type t = c1.GetType();

foreach (PropertyInfo p in t.GetProperties())
{
if (p.GetValue(c1,null)!=p.GetValue(c2,null))
return false;
}
return true;
}
}
}



bengamin said:
Hi,Marcin

Thany you !

The example you give have a presupposition/precondition that we must know
the properties ,but the fact is we don't know the properties.

Today i found a new way to implement the function
This is the example code:

Class1 a = new Class1();
Class1 b = new Class1();
XmlSerializer formatter = new XmlSerializer(typeof(Class1));
Byte[] buff = new Byte[1024];
Stream stream = new MemoryStream(buff);
formatter.Serialize(stream, a);
Byte[] buff1 = new Byte[1024];
Stream stream1 = new MemoryStream(buff1);
formatter.Serialize(stream1, b);

for(int i = 0 ; i < buff.Length ; i ++ )
{
if (buff != buff1)
{
label1.Text = "false";
return;
}
}
label1.Text = "true";


But there is some problem :
1, HashTable can not be xmlserializer;
2, The sample class i used for example is ok ,but when turn to the class of
our business layer,
there come an error when step into "Stream stream = new
MemoryStream(buff);"


I don't know why ,is somebody can give me some help?

Thank you!



Marcin Grzêbski said:
Hi bengamin,

Here is your sample:

public class Person
: IComparable
{
private int age;
private string lastName;
private string firstName;
private bool maleGender;

public int CompareTo(object obj) {
Person secondPerson=obj as Person;
if( secondPerson==null ) {
throw new ArgumentNullException("obj");
}
int result;
result=(age-obj.age);
if( result!=0 ) {
return result;
}
result=lastName.CompareTo(obj.lastName);
if( result!=0 ) {
return result;
}
result=firstName.CompareTo(obj.firstName);
if( result!=0 ) {
return result;
}
result=maleGender.CompareTo(obj.maleGender);
return result;
}

}

Cheers!

Marcin
 
Hi again,


The example you give have a presupposition/precondition that we must know
the properties ,but the fact is we don't know the properties.

I'm sorry. But i don't know how you want to compare something
that you don't know?
If you're desinging a class then you should know its properties.
You can not know its base class private (or internal) properties
but the others should be visible.

There's now universal method to implement IComparable interface.

If you want to write universal comparator, then you've got
a lot of work to do... :(
Today i found a new way to implement the function
This is the example code:

Class1 a = new Class1();
Class1 b = new Class1();
XmlSerializer formatter = new XmlSerializer(typeof(Class1));
Byte[] buff = new Byte[1024];
Stream stream = new MemoryStream(buff);
formatter.Serialize(stream, a);
Byte[] buff1 = new Byte[1024];
Stream stream1 = new MemoryStream(buff1);
formatter.Serialize(stream1, b);

for(int i = 0 ; i < buff.Length ; i ++ )
{
if (buff != buff1)
{
label1.Text = "false";
return;
}
}
label1.Text = "true";


But there is some problem :
1, HashTable can not be xmlserializer;
2, The sample class i used for example is ok ,but when turn to the class of
our business layer,
there come an error when step into "Stream stream = new
MemoryStream(buff);"


If you want to serialize Hashtable then you can serialize its
keys and values (as a tables)
I don't know why ,is somebody can give me some help?

Thank you!

Cheers!

Marcin
 
Hi,

With Reflection ,i get the code like this
And it works very well when there is no Array ,ArrayList or HashTable etc...
I don't know how to deal with Array ,can you give me some advice ?
Thank You!

private bool Compare(Object a, Object b)
{
if (a != null && b != null)
{
Type t = a.GetType();

foreach(PropertyInfo p in t.GetProperties())
{
if (p.PropertyType.ToString() != "System.Object")
{
if ((!p.PropertyType.IsValueType) && (p.PropertyType.ToString() !=
"System.String"))
{
if( Compare(p.GetValue(a,null),p.GetValue(b,null)))
continue;
else
return false;
}
else
{
if (Convert.ToString(p.GetValue(a,null)) !=
Convert.ToString(p.GetValue(b,null)))
return false;
}
}
}
return true;
}
else
{
if (a == null && b == null)
return true;
return false;
}
}


richlm said:
If you really want to do byte comparison, you would be better off using
BinaryFormatter.
(Note your XmlSerializer only takes the public properties). See Compare1
below.

Another good solution where you don't know the properties is to use
reflection. See Compare2 below - much simpler.

(sample code for illustration - not tested...)
*************

using System;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using System.Reflection;

namespace ClassLibrary1
{
/// <summary>
/// Summary description for Class1.
/// </summary>
public class Class1
{
int i = 0;
string s = "";
object o = null;

public Class1()
{
}

public static bool Compare1( Class1 c1, Class1 c2 )
{
BinaryFormatter f1 = new BinaryFormatter();
MemoryStream s1 = new MemoryStream();
BinaryFormatter f2 = new BinaryFormatter();
MemoryStream s2 = new MemoryStream();

f1.Serialize(s1,c1);
f2.Serialize(s2,c2);

byte[] buf1 = s1.ToArray();
byte[] buf2 = s2.ToArray();

if (buf1.Length==buf2.Length)
return false;

for (int i=0; i<buf1.Length; i++)
{
if (buf1!=buf2)
return false;
}
}

public static bool Compare2( Class1 c1, Class1 c2 )
{
Type t = c1.GetType();

foreach (PropertyInfo p in t.GetProperties())
{
if (p.GetValue(c1,null)!=p.GetValue(c2,null))
return false;
}
return true;
}
}
}



bengamin said:
Hi,Marcin

Thany you !

The example you give have a presupposition/precondition that we must know
the properties ,but the fact is we don't know the properties.

Today i found a new way to implement the function
This is the example code:

Class1 a = new Class1();
Class1 b = new Class1();
XmlSerializer formatter = new XmlSerializer(typeof(Class1));
Byte[] buff = new Byte[1024];
Stream stream = new MemoryStream(buff);
formatter.Serialize(stream, a);
Byte[] buff1 = new Byte[1024];
Stream stream1 = new MemoryStream(buff1);
formatter.Serialize(stream1, b);

for(int i = 0 ; i < buff.Length ; i ++ )
{
if (buff != buff1)
{
label1.Text = "false";
return;
}
}
label1.Text = "true";


But there is some problem :
1, HashTable can not be xmlserializer;
2, The sample class i used for example is ok ,but when turn to the class of
our business layer,
there come an error when step into "Stream stream = new
MemoryStream(buff);"


I don't know why ,is somebody can give me some help?

Thank you!



Marcin Grzêbski said:
Hi bengamin,

Here is your sample:

public class Person
: IComparable
{
private int age;
private string lastName;
private string firstName;
private bool maleGender;

public int CompareTo(object obj) {
Person secondPerson=obj as Person;
if( secondPerson==null ) {
throw new ArgumentNullException("obj");
}
int result;
result=(age-obj.age);
if( result!=0 ) {
return result;
}
result=lastName.CompareTo(obj.lastName);
if( result!=0 ) {
return result;
}
result=firstName.CompareTo(obj.firstName);
if( result!=0 ) {
return result;
}
result=maleGender.CompareTo(obj.maleGender);
return result;
}

}

Cheers!

Marcin

Thank you for your help!
Can you give us some example?

"Marcin Grzêbski" <[email protected]> ????

Hi,

Good practise is to implement "IComparable" interface.

int CompareTo(Object obj)
- it should return zero if "obj" is equal to base object.

Then you have to (easily) override the "Equals()", as follow:

public override bool Equals(Object obj) {
return (this.CompareTo(obj)==0);
}

Cheers

Marcin


Hi,

I have a C# class and two instance of the class;

the class have some property.

I want to compare the property value of the two instance

How should i do? override == ? use delegate ?

I am sorry ,my english was poor.

 
Hi,

After testing ,I found the byte comparison is not a reliable way
first, I get data from web page and store into a instance
second, I store the instance to a session ,
and then I get data from the web page again without any changeing ,
even the web page data didn't change, there will be something like
arraylist._version have changed and the compare function will return false ;

So, i think we should found another solution or try to finish the solution
of reflection

Go on please!

Thank you!

richlm said:
If you really want to do byte comparison, you would be better off using
BinaryFormatter.
(Note your XmlSerializer only takes the public properties). See Compare1
below.

Another good solution where you don't know the properties is to use
reflection. See Compare2 below - much simpler.

(sample code for illustration - not tested...)
*************

using System;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using System.Reflection;

namespace ClassLibrary1
{
/// <summary>
/// Summary description for Class1.
/// </summary>
public class Class1
{
int i = 0;
string s = "";
object o = null;

public Class1()
{
}

public static bool Compare1( Class1 c1, Class1 c2 )
{
BinaryFormatter f1 = new BinaryFormatter();
MemoryStream s1 = new MemoryStream();
BinaryFormatter f2 = new BinaryFormatter();
MemoryStream s2 = new MemoryStream();

f1.Serialize(s1,c1);
f2.Serialize(s2,c2);

byte[] buf1 = s1.ToArray();
byte[] buf2 = s2.ToArray();

if (buf1.Length==buf2.Length)
return false;

for (int i=0; i<buf1.Length; i++)
{
if (buf1!=buf2)
return false;
}
}

public static bool Compare2( Class1 c1, Class1 c2 )
{
Type t = c1.GetType();

foreach (PropertyInfo p in t.GetProperties())
{
if (p.GetValue(c1,null)!=p.GetValue(c2,null))
return false;
}
return true;
}
}
}



bengamin said:
Hi,Marcin

Thany you !

The example you give have a presupposition/precondition that we must know
the properties ,but the fact is we don't know the properties.

Today i found a new way to implement the function
This is the example code:

Class1 a = new Class1();
Class1 b = new Class1();
XmlSerializer formatter = new XmlSerializer(typeof(Class1));
Byte[] buff = new Byte[1024];
Stream stream = new MemoryStream(buff);
formatter.Serialize(stream, a);
Byte[] buff1 = new Byte[1024];
Stream stream1 = new MemoryStream(buff1);
formatter.Serialize(stream1, b);

for(int i = 0 ; i < buff.Length ; i ++ )
{
if (buff != buff1)
{
label1.Text = "false";
return;
}
}
label1.Text = "true";


But there is some problem :
1, HashTable can not be xmlserializer;
2, The sample class i used for example is ok ,but when turn to the class of
our business layer,
there come an error when step into "Stream stream = new
MemoryStream(buff);"


I don't know why ,is somebody can give me some help?

Thank you!



Marcin Grzêbski said:
Hi bengamin,

Here is your sample:

public class Person
: IComparable
{
private int age;
private string lastName;
private string firstName;
private bool maleGender;

public int CompareTo(object obj) {
Person secondPerson=obj as Person;
if( secondPerson==null ) {
throw new ArgumentNullException("obj");
}
int result;
result=(age-obj.age);
if( result!=0 ) {
return result;
}
result=lastName.CompareTo(obj.lastName);
if( result!=0 ) {
return result;
}
result=firstName.CompareTo(obj.firstName);
if( result!=0 ) {
return result;
}
result=maleGender.CompareTo(obj.maleGender);
return result;
}

}

Cheers!

Marcin

Thank you for your help!
Can you give us some example?

"Marcin Grzêbski" <[email protected]> ????

Hi,

Good practise is to implement "IComparable" interface.

int CompareTo(Object obj)
- it should return zero if "obj" is equal to base object.

Then you have to (easily) override the "Equals()", as follow:

public override bool Equals(Object obj) {
return (this.CompareTo(obj)==0);
}

Cheers

Marcin


Hi,

I have a C# class and two instance of the class;

the class have some property.

I want to compare the property value of the two instance

How should i do? override == ? use delegate ?

I am sorry ,my english was poor.

 
The default implementation of equals performs reference equality - that's
not what is being asked for here.
What we are talking about is a general solution for value equality.
 
Back
Top