Asserting that all public properties match

1,279 views
Skip to first unread message

Simone Busoli

unread,
Jan 8, 2009, 12:17:58 PM1/8/09
to nunit-...@googlegroups.com
Hello, quite often I need to check that two objects behave as value types, that is, they are equal if all their fields are equal. Actually, usually I need to check that their public state is equal, that is, their public properties.
I usually do it by overriding Equals and friends, but most of the time it doesn't have any business meaning, and it's used only for testing. What do you think about this? Should we need a constraint?

Olof Bjarnason

unread,
Jan 8, 2009, 12:27:01 PM1/8/09
to nunit-...@googlegroups.com
+1 on that. Lots of test code are custom Equality checks.

public properties, public fields. Nothing else.

2009/1/8 Simone Busoli <simone...@gmail.com>:
--
Min blogg:
http://olofb.wordpress.com
[My blog, in Swedish]

Charlie Poole

unread,
Jan 8, 2009, 2:48:52 PM1/8/09
to nunit-...@googlegroups.com
Hi Simone,
 
I like to start with the code we wish  we could write...
 
It strikes me that this is quite like the "memberwise" comparison that Olof was proposing,
except that the "members" are properties rather than items contained in a collection.
 
It seems to me that either or both of them can be implemented by means of a
modifier on the equal constraint. I'm not sure whethe we could use the same
modifier and distinquish by context, or if a different modifier is better.
 
This would imply something like...
 
  Assert.That( actual, Is.EqualTo( expected).PropertyWise);
 
An alternative would be a new constraint, with syntax like...
 
  Assert.That( actual, Has.SamePropertyValuesAs( expected ))
 
I don't particularly like either of the names I used, but we can work on that.
 
Charlie
 
 


From: nunit-...@googlegroups.com [mailto:nunit-...@googlegroups.com] On Behalf Of Simone Busoli
Sent: Thursday, January 08, 2009 9:18 AM
To: nunit-...@googlegroups.com
Subject: [nunit-discuss] Asserting that all public properties match

Olof Bjarnason

unread,
Jan 8, 2009, 3:44:37 PM1/8/09
to nunit-...@googlegroups.com
2009/1/8 Charlie Poole <cha...@nunit.com>:
> Hi Simone,
>
> I like to start with the code we wish we could write...
>
> It strikes me that this is quite like the "memberwise" comparison that Olof
> was proposing,
> except that the "members" are properties rather than items contained in a
> collection.

Yeah the proposed ElementWise constraint was supposed to apply
whatever "singleton-constraint" was written on each element-pair in
the two supplied IEnumerable objects:

Assert.That( actual, Is.SameAs( expected ).ElementWise); // IIRC

I've tried implementing a "general value-equality" in C# when I got
tired of writing custom Equal-overrides- they are quite redtapa:ish
after awhile - but it was not as simple as I had hoped.

For example, it is common in my classes to use member variables of type List<T>.

List<T> has a public property "Capacity" (IIRC) which says how many
potential elements it has, before it will re-grow itself (when
reaching capacity). That has nothing to do with the equality of two
lists IMHO. Don't know how to handle that -- tried to add some kind of
"overloads" to the ValueEquality-class (which I called my class) but
it started to feel to expensive to invest more time in.

So I gave up the "general approach" and tried to go the BDD "don't
test state"-road -- which I'm still trying to walk. However, that road
is quite bumpy - I think I would need a tank or something to go any
further in C#/NUnit - so I would appreciate if NUnit could supply a
general ValueEquals-implementation.


>
> It seems to me that either or both of them can be implemented by means of a
> modifier on the equal constraint. I'm not sure whethe we could use the same
> modifier and distinquish by context, or if a different modifier is better.
>
> This would imply something like...
>
> Assert.That( actual, Is.EqualTo( expected).PropertyWise);
>
> An alternative would be a new constraint, with syntax like...
>
> Assert.That( actual, Has.SamePropertyValuesAs( expected ))
>
> I don't particularly like either of the names I used, but we can work on
> that.
>
> Charlie
>
>
>
> ________________________________
> From: nunit-...@googlegroups.com [mailto:nunit-...@googlegroups.com]
> On Behalf Of Simone Busoli
> Sent: Thursday, January 08, 2009 9:18 AM
> To: nunit-...@googlegroups.com
> Subject: [nunit-discuss] Asserting that all public properties match
>
> Hello, quite often I need to check that two objects behave as value types,
> that is, they are equal if all their fields are equal. Actually, usually I
> need to check that their public state is equal, that is, their public
> properties.
> I usually do it by overriding Equals and friends, but most of the time it
> doesn't have any business meaning, and it's used only for testing. What do
> you think about this? Should we need a constraint?
> >
>



Simone Busoli

unread,
Jan 8, 2009, 4:22:55 PM1/8/09
to nunit-...@googlegroups.com
I think an intuitive way to express it is using the ValueType word in some way, something everyone should be aware of. RhinoMocks uses an even more explicit approach, AllPropertiesMatch.

Charlie Poole

unread,
Jan 8, 2009, 4:22:34 PM1/8/09
to nunit-...@googlegroups.com
Hi Olof,

> List<T> has a public property "Capacity" (IIRC) which says
> how many potential elements it has, before it will re-grow
> itself (when reaching capacity). That has nothing to do with
> the equality of two lists IMHO.

Agreed. This is reminiscent of the notion of "logical const"
in C++ - where changing certain variables doesn't really
count as breaking constness.

> Don't know how to handle that
> -- tried to add some kind of "overloads" to the
> ValueEquality-class (which I called my class) but it started
> to feel to expensive to invest more time in.
>
> So I gave up the "general approach" and tried to go the BDD
> "don't test state"-road -- which I'm still trying to walk.
> However, that road is quite bumpy - I think I would need a
> tank or something to go any further in C#/NUnit - so I would
> appreciate if NUnit could supply a general ValueEquals-implementation.

I suppose there could be an overload that passed a list of
properties to use - or a list of those to exclude.

For the general case, what about a syntax like...

AssertThat( PropertiesOf(actual), Are.EqualTo( PropertiesOf(Expected) ) );

?


Charlie

Simone Busoli

unread,
Jan 8, 2009, 4:26:38 PM1/8/09
to nunit-...@googlegroups.com
On Thu, Jan 8, 2009 at 10:22 PM, Charlie Poole <cha...@nunit.com> wrote:
AssertThat( PropertiesOf(actual), Are.EqualTo( PropertiesOf(Expected) ) );

Honestly, I don't like it very much. Changing the way you write the first operand of the assertion is not intuitive and hard to discover.

Charlie Poole

unread,
Jan 8, 2009, 4:37:14 PM1/8/09
to nunit-...@googlegroups.com
Hi Simone,

I think an intuitive way to express it is using the ValueType word in some way, something everyone should be aware of.  
 
I'm afraid I'm not. :-( Except that it's the name of a BCL class. Care to educate me?
 
RhinoMocks uses an even more explicit approach, AllPropertiesMatch. 
 
I like it, at least for Assert and as the name of a constraint. But I can't figure
out the fluent syntax for it. I could write...
 
  Assert.That(actual, Has.All.Properties.EqualTo( expected ))
 
but that seems ambiguous to me. Either
 
1) All properties of actual are equal to expected OR
2) All properties of actual are equal to the corresponding property of expected.
 
But I'm a nitpicker, so if nobody else thinks it's ambiguous, I'll withdraw
my objection.
 
Charlie

Olof Bjarnason

unread,
Jan 8, 2009, 4:42:08 PM1/8/09
to nunit-...@googlegroups.com
2009/1/8 Charlie Poole <cha...@nunit.com>:
>
> Hi Olof,
>
>> List<T> has a public property "Capacity" (IIRC) which says
>> how many potential elements it has, before it will re-grow
>> itself (when reaching capacity). That has nothing to do with
>> the equality of two lists IMHO.
>
> Agreed. This is reminiscent of the notion of "logical const"
> in C++ - where changing certain variables doesn't really
> count as breaking constness.
>
>> Don't know how to handle that
>> -- tried to add some kind of "overloads" to the
>> ValueEquality-class (which I called my class) but it started
>> to feel to expensive to invest more time in.
>>
>> So I gave up the "general approach" and tried to go the BDD
>> "don't test state"-road -- which I'm still trying to walk.
>> However, that road is quite bumpy - I think I would need a
>> tank or something to go any further in C#/NUnit - so I would
>> appreciate if NUnit could supply a general ValueEquals-implementation.
>
> I suppose there could be an overload that passed a list of
> properties to use - or a list of those to exclude.
>
> For the general case, what about a syntax like...
>
> AssertThat( PropertiesOf(actual), Are.EqualTo( PropertiesOf(Expected) ) );

Problem is value-equality must be recursive. So if I have a class A

public class A {
public int SomeInt;
public List<int> TheList { get; }
}

.. what would I write? I don't want exclude "TheList" from the
comparison (since it is part of the "value" of an object of type A),
yet I have to express somehow that A.TheList.Capacity should be
ignored.

Simone Busoli

unread,
Jan 8, 2009, 4:47:34 PM1/8/09
to nunit-...@googlegroups.com
On Thu, Jan 8, 2009 at 10:37 PM, Charlie Poole <cha...@nunit.com> wrote:
I think an intuitive way to express it is using the ValueType word in some way, something everyone should be aware of.  
 
I'm afraid I'm not. :-( Except that it's the name of a BCL class. Care to educate me?

Fire up Reflector, select the Int32 type, switch from C# to IL and you see that it inherits from ValueType. In the .NET FX, all primitive types, except for string and arrays, are value types. Go see how ValueType implements Equals and you see that it compares the value of the fields of the object, not their reference, which is the default implementation of Equals in the Object class.
 
 
RhinoMocks uses an even more explicit approach, AllPropertiesMatch. 
 
I like it, at least for Assert and as the name of a constraint. But I can't figure
out the fluent syntax for it. I could write...
 
  Assert.That(actual, Has.All.Properties.EqualTo( expected ))
 
but that seems ambiguous to me. Either
 
1) All properties of actual are equal to expected OR
2) All properties of actual are equal to the corresponding property of expected.
 
But I'm a nitpicker, so if nobody else thinks it's ambiguous, I'll withdraw
my objection.

Yes I think it's ambiguous but I don't like it much anyways since it is too verbose. 
I'm still thinking about a good way to express it.

Simone Busoli

unread,
Jan 8, 2009, 4:49:56 PM1/8/09
to nunit-...@googlegroups.com
The .NET fx doesn't implement it recursively, and it's the way I intend it. I want my actual object to be treated as a value type, not its fields. I'll call Equals on the fields, however it is implemented in the runtime type.

Charlie Poole

unread,
Jan 8, 2009, 6:43:57 PM1/8/09
to nunit-...@googlegroups.com
Hi Olof,

> Problem is value-equality must be recursive. So if I have a class A
>
> public class A {
> public int SomeInt;
> public List<int> TheList { get; }
> }
>
> .. what would I write? I don't want exclude "TheList" from
> the comparison (since it is part of the "value" of an object
> of type A), yet I have to express somehow that
> A.TheList.Capacity should be ignored.

You're right - I didn't think of that.

Charlie

Charlie Poole

unread,
Jan 8, 2009, 7:51:34 PM1/8/09
to nunit-...@googlegroups.com
Hi Simone,

On Thu, Jan 8, 2009 at 10:37 PM, Charlie Poole <cha...@nunit.com> wrote:
I think an intuitive way to express it is using the ValueType word in some way, something everyone should be aware of.  
 
I'm afraid I'm not. :-( Except that it's the name of a BCL class. Care to educate me?

Fire up Reflector, select the Int32 type, switch from C# to IL and you see that it inherits from ValueType. In the .NET FX, all primitive types, except for string and arrays, are value types. Go see how ValueType implements Equals and you see that it compares the value of the fields of the object, not their reference, which is the default implementation of Equals in the Object class.
 
Yes, that's what I meant by the BCL class. So, you're suggesting we use some syntax
like Is.EqualAsValueType()? That would be confusing to me, if the object in question
were not a ValueType.
 
 
RhinoMocks uses an even more explicit approach, AllPropertiesMatch. 
 
I like it, at least for Assert and as the name of a constraint. But I can't figure
out the fluent syntax for it. I could write...
 
  Assert.That(actual, Has.All.Properties.EqualTo( expected ))
 
but that seems ambiguous to me. Either
 
1) All properties of actual are equal to expected OR
2) All properties of actual are equal to the corresponding property of expected.
 
But I'm a nitpicker, so if nobody else thinks it's ambiguous, I'll withdraw
my objection.

Yes I think it's ambiguous but I don't like it much anyways since it is too verbose. 
I'm still thinking about a good way to express it. 
 
OK... let us know if you think of something.
 
Charlie
 

Thierry Lach

unread,
Jan 8, 2009, 9:20:13 PM1/8/09
to nunit-...@googlegroups.com
How about

Assert.That(actual, Is.EqualTo(expected).InAllProperties;

and

Assert.That(actual, Is.EqualTo(expected).InAllProperties.Except(namelist);

and maybe even

Assert.That(actual, Is.EqualTo(expected).InAllProperties.Except(namelist).Recursive;

(implying that without the .Recursive it would not navigate to child objects)
--
---
Do not follow where the path may lead. Go instead where there is no path and leave a trail.
~Ralph Waldo Emerson

Olof Bjarnason

unread,
Jan 9, 2009, 12:37:00 AM1/9/09
to nunit-...@googlegroups.com
2009/1/8 Simone Busoli <simone...@gmail.com>:
> The .NET fx doesn't implement it recursively, and it's the way I intend it.
> I want my actual object to be treated as a value type, not its fields. I'll
> call Equals on the fields, however it is implemented in the runtime type.
>

Yeah that is one idea - however that would not make comparison between
objects having for example List<T> members, or even arrays. That would
make the comparison a bit limited IMHO.


> On Thu, Jan 8, 2009 at 10:42 PM, Olof Bjarnason <olof.bj...@gmail.com>
> wrote:
>>
>> Problem is value-equality must be recursive. So if I have a class A
>>
>> public class A {
>> public int SomeInt;
>> public List<int> TheList { get; }
>> }
>>
>> .. what would I write? I don't want exclude "TheList" from the
>> comparison (since it is part of the "value" of an object of type A),
>> yet I have to express somehow that A.TheList.Capacity should be
>> ignored.
>
> >
>



Simone Busoli

unread,
Jan 9, 2009, 5:39:11 AM1/9/09
to nunit-...@googlegroups.com
I think that would be the correct way to describe it, since the equality would be implemented exactly as it is implemented in the .NET fx ValueType class. And again, not recursively, that's what ValueType does, at least.

Simone Busoli

unread,
Jan 9, 2009, 5:43:34 AM1/9/09
to nunit-...@googlegroups.com
I'm thinking about:

Has.AllPropertiesEqualTo(expected)
Has.PropertiesEqualTo(expected, params string[] "names of properties to include in the comparison")
Is.EqualTo(expected).AsValueType <-- the most correct I think, since it's not ambiguous, at least if you know how ValueTypes work

Simone Busoli

unread,
Jan 9, 2009, 5:52:12 AM1/9/09
to nunit-...@googlegroups.com
I don't like it much because it's an ambiguous concept. I mean, you compare the properties on the object as if it was a value type, but then treat collections differently and don't call Equals on them but instead iterate through their elements, and again and again and again. I mean, why are collections special? To me, iterating through collections in this case, instead of calling equals on them, is just like reflecting over other kinds of the root objects members and comparing their properties.

Example:

class Root
{
  int value;
  ArrayList collection;
  WebClient webClient;
}

So, as I intent it two instances of Root are equal with value type semantics if their value field is equal and both collection and webClient fields reference the same object in memory, respectively.
How you intend it is that two instances of root are equal if their value field is equal, webClient points to the same location in memory and the members of the collection field are equal. To me this is ambiguous. So, if we iterate the elements of the collection, then why don't we inspect the properties of webClient and compare their values? It's ambiguous.

Olof Bjarnason

unread,
Jan 9, 2009, 7:14:52 AM1/9/09
to nunit-...@googlegroups.com
2009/1/9 Simone Busoli <simone...@gmail.com>:
> I don't like it much because it's an ambiguous concept. I mean, you compare
> the properties on the object as if it was a value type, but then treat
> collections differently and don't call Equals on them but instead iterate
> through their elements, and again and again and again. I mean, why are
> collections special? To me, iterating through collections in this case,
> instead of calling equals on them, is just like reflecting over other kinds
> of the root objects members and comparing their properties.
> Example:
> class Root
> {
> int value;
> ArrayList collection;
> WebClient webClient;
> }
> So, as I intent it two instances of Root are equal with value type semantics
> if their value field is equal and both collection and webClient fields
> reference the same object in memory, respectively.
> How you intend it is that two instances of root are equal if their value
> field is equal, webClient points to the same location in memory and the
> members of the collection field are equal. To me this is ambiguous. So, if
> we iterate the elements of the collection, then why don't we inspect the
> properties of webClient and compare their values? It's ambiguous.

As I said, the general ValueEquality is complicated, that's why I
abandonen the general case.

ValueType-comparison is nice, and useful in some special cases.

For example, say you have this:

class Person { string FullName; }
class ClassRoom {
List<Person> Pupils = new List<Person>();
int Id = 0;
}

var Olof = new Person { FullName = "Olof"; }
var Simone = new Person { FullName = "Simone"; }
var room1 = new ClassRoom();
room1.Id = 1;
room1.Pupils.Add(Olof);
room1.Pupils.Add(Simone);
var room1b = new ClassRoom();
room1b.Id = 1;
room1b.Pupils.Add(Olof);
room1b.Pupils.Add(Simone);

Are room1 and room1b the same? No, they are different objects in memory.

Are room1 and room1b equal? They are indistinguisable in their public
interface (except for, perhaps, the Capacity field of the List<Person>
objects, and of course that the List's are two different objects in
memory).

Seen as value objects - or pure data model objects - they are the same.

Seen as ValueType objects - not the same.

Maybe this is a pragmatic approach to this: Add ValueType equality to
NUnit now, the way Simone describes it. Skip the general case for now,
until we learn more.

>
> On Fri, Jan 9, 2009 at 6:37 AM, Olof Bjarnason <olof.bj...@gmail.com>
> wrote:
>>
>> Yeah that is one idea - however that would not make comparison between
>> objects having for example List<T> members, or even arrays. That would
>> make the comparison a bit limited IMHO.
>
> >
>



Simone Busoli

unread,
Jan 9, 2009, 7:23:31 AM1/9/09
to nunit-...@googlegroups.com
What I don't get is this: why do you consider Pupils as something to go deep into and, say, another property of type <code>class Pair { object First; object Second;  }</code> not? 

Olof Bjarnason

unread,
Jan 9, 2009, 8:13:13 AM1/9/09
to nunit-...@googlegroups.com
2009/1/9 Simone Busoli <simone...@gmail.com>:
> What I don't get is this: why do you consider Pupils as something to go deep
> into and, say, another property of type <code>class Pair { object First;
> object Second; }</code> not?

I would definately consider using Value-equality on the First and
Second objects of Pairs too, in the general case, thus recursing down.
So no special case of List (or IEnumerables). That is the only
"mathematically sane" thing to do IMHO.

I could just blame Microsoft for having the public Capacity
property/field in their generic list type - but then again this is
where we are, and have to deal with it. One way is just implementing
all collections by myself of course, to make them easier to test - and
that is solution that might be viable, considering the situation.

What I really want, I have come to an insight of, is immutable objects
with value-like equality. Much like data in Haskell or other
functional languages. Not having to think about "memory" and
"pointers" -- which is what you have to do in C#, even though we got
rid of the physical pointer legacy to an extent with the switch from
C/C++ to .NET.

Sorry for my rambling, but this is a problem I have been thinking of a lot..

Henning

unread,
Jan 11, 2009, 3:42:45 AM1/11/09
to NUnit-Discuss
Hmm, I've been struggeling with this comparison in the last few weeks
as well. I found a pragmatical solution at
http://stackoverflow.com/questions/318210/compare-equality-between-two-objects-in-nunit,
regardless of how good it looks - as I mentioned: it at least does the
job! :)

Well, I needed to make some little modifications.

Based on Olof's example consider something like this:

class Person { string FullName; }
class ClassRoom {
IList<Person> Pupils;
int Id = 0;

}

var Olof = new Person { FullName = "Olof"; }
var Simone = new Person { FullName = "Simone"; }
var room1 = new ClassRoom();
room1.Id = 1;
room1.Pupils = new List<Person>();
room1.Pupils.Add(Olof);
room1.Pupils.Add(Simone);
var room1b = new ClassRoom();
room1b.Id = 1;
room1b.Pupils = new Collection<Pupils>();
room1b.Pupils.Add(Olof);
room1b.Pupils.Add(Simone);

In this scenario the type of the pupils differ, the actual values
don't!

On 9 Jan., 13:14, "Olof Bjarnason" <olof.bjarna...@gmail.com> wrote:
> 2009/1/9 Simone Busoli <simone.bus...@gmail.com>:
> > On Fri, Jan 9, 2009 at 6:37 AM, Olof Bjarnason <olof.bjarna...@gmail.com>

Olof Bjarnason

unread,
Jan 11, 2009, 11:55:23 AM1/11/09
to nunit-...@googlegroups.com
2009/1/11 Henning <hennin...@googlemail.com>:
That is a good observation - but having IList<T> is better since a
naive recursive-descent through the public properties of two objects
implementing IList<T> (like Pupils for example) would do what I would
call "the mathematically sane thing" (comparing _values_, not
_pointers_).

Simone Busoli

unread,
Jan 11, 2009, 7:36:24 PM1/11/09
to nunit-...@googlegroups.com
Any ideas about how to implement a first version of this, which compares, maybe, the public properties? I thought about creating a custom IComparer to put in NUnit and eventually provide a shortcut as a constraint modifier.

Olof Bjarnason

unread,
Jan 11, 2009, 7:41:09 PM1/11/09
to nunit-...@googlegroups.com
2009/1/12 Simone Busoli <simone...@gmail.com>:
> Any ideas about how to implement a first version of this, which compares,
> maybe, the public properties? I thought about creating a custom IComparer to
> put in NUnit and eventually provide a shortcut as a constraint modifier.
>

Are you talking about ValueType equality or the more general "value
equality" that I've been talking about?

I had a bit of an "aha moment" when someone mentioned IList -- such
more abstract types for member variables/properties might be the key
for a general ValueEquality comparison.

Simone Busoli

unread,
Jan 11, 2009, 7:46:07 PM1/11/09
to nunit-...@googlegroups.com
I'd first go with simple value equality, at least until there's agreement about how to implement a generic value equality.

Olof Bjarnason

unread,
Jan 11, 2009, 7:58:05 PM1/11/09
to nunit-...@googlegroups.com
2009/1/12 Simone Busoli <simone...@gmail.com>:
> I'd first go with simple value equality, at least until there's agreement
> about how to implement a generic value equality.

OK this I call ValueType equality - I think someone mentioned that
name earlier in this (long) thread.

+1 on that - go for the simpler things first.

Henning

unread,
Jan 13, 2009, 3:29:45 AM1/13/09
to NUnit-Discuss
So just that I get this right:

1. I basically want to know if two objects are ValueType-Equal -
right? OK, so I naive have to iterate over all properties and compare
the values (however this is being done!).

2. So when I find some kind of IEnumerable I also have to compare the
values of this numerable as well, so this would be kinda recursive.

But there is a problem: I currently test, wheter my NHibernate-
Mappings are working correct, by comparing the in-code constructed
object with whatever I got from the DB. Since I have a bi-directional
navigation (customer->order; order->customer) this could result in an
endless-loop. So this needs to be detected.

On 12 Jan., 01:58, "Olof Bjarnason" <olof.bjarna...@gmail.com> wrote:
> 2009/1/12 Simone Busoli <simone.bus...@gmail.com>:
>
> > I'd first go with simple value equality, at least until there's agreement
> > about how to implement a generic value equality.
>
> OK this I call ValueType equality - I think someone mentioned that
> name earlier in this (long) thread.
>
> +1 on that - go for the simpler things first.
>
>
>
>
>
> > On Mon, Jan 12, 2009 at 1:41 AM, Olof Bjarnason <olof.bjarna...@gmail.com>
> > wrote:
>
> >> 2009/1/12 Simone Busoli <simone.bus...@gmail.com>:
> >> > Any ideas about how to implement a first version of this, which
> >> > compares,
> >> > maybe, the public properties? I thought about creating a custom
> >> > IComparer to
> >> > put in NUnit and eventually provide a shortcut as a constraint modifier.
>
> >> Are you talking about ValueType equality or the more general "value
> >> equality" that I've been talking about?
>
> >> I had a bit of an "aha moment" when someone mentioned IList -- such
> >> more abstract types for member variables/properties might be the key
> >> for a general ValueEquality comparison.
>
> >> > On Sun, Jan 11, 2009 at 5:55 PM, Olof Bjarnason
> >> > <olof.bjarna...@gmail.com>
> >> > wrote:
>
> >> >> 2009/1/11 Henning <henning.ei...@googlemail.com>:
>
> >> >> > Hmm, I've been struggeling with this comparison in the last few weeks
> >> >> > as well. I found a pragmatical solution at
>
> >> >> >http://stackoverflow.com/questions/318210/compare-equality-between-tw...,

Simone Busoli

unread,
Jan 13, 2009, 3:45:18 AM1/13/09
to nunit-...@googlegroups.com
Yes, going further than comparing the properties can be tricky, that's why we need to agree on a way to do this.

Olof Bjarnason

unread,
Jan 13, 2009, 3:47:55 AM1/13/09
to nunit-...@googlegroups.com
How exactly does the value-type comparison for structures work? Only
public, or _all_ fields? What about properties? Reference types?
Structs in structs?

Illustratrated:
struct A {
public int I;
internal B;
private C;
}
class C { public int J; }

Given A a1 = ...; A a2 = ...; what does "a1.Equals(a2)" mean?


2009/1/13 Simone Busoli <simone...@gmail.com>:

Simone Busoli

unread,
Jan 13, 2009, 6:54:12 AM1/13/09
to nunit-...@googlegroups.com
Reflector -> ValueType -> Equals

Olof Bjarnason

unread,
Jan 13, 2009, 6:56:54 AM1/13/09
to nunit-...@googlegroups.com
2009/1/13 Simone Busoli <simone...@gmail.com>:
> Reflector -> ValueType -> Equals

I'm not sure I understand what you mean Simone.

Simone Busoli

unread,
Jan 13, 2009, 6:58:15 AM1/13/09
to nunit-...@googlegroups.com
I mean that you can look at the implementation of the Equals method on the ValueType class by using reflector.

Olof Bjarnason

unread,
Jan 13, 2009, 7:12:28 AM1/13/09
to nunit-...@googlegroups.com
Wow, great tool! Thanks for the hint.

Here is the disassembled version of System.ValueType.Equals:

public override bool Equals(object obj)
{
if (obj == null)
{
return false;
}
RuntimeType type = (RuntimeType) base.GetType();
RuntimeType type2 = (RuntimeType) obj.GetType();
if (type2 != type)
{
return false;
}
object a = this;
if (CanCompareBits(this))
{
return FastEqualsCheck(a, obj);
}
FieldInfo[] fields = type.GetFields(BindingFlags.NonPublic |
BindingFlags.Public | BindingFlags.Instance);
for (int i = 0; i < fields.Length; i++)
{
object obj3 = ((RtFieldInfo) fields[i]).InternalGetValue(a, false);
object obj4 = ((RtFieldInfo) fields[i]).InternalGetValue(obj, false);
if (obj3 == null)
{
if (obj4 != null)
{
return false;
}
}
else if (!obj3.Equals(obj4))
{
return false;
}
}
return true;
}



2009/1/13 Simone Busoli <simone...@gmail.com>:

Simone Busoli

unread,
Jan 13, 2009, 7:16:49 AM1/13/09
to nunit-...@googlegroups.com
Actually, I was wrong on the fact that the AllPropertiesMatch constraint that there's in RhinoMocks does a value type comparison, in reality it does much more, and could be a good base: https://rhino-tools.svn.sourceforge.net/svnroot/rhino-tools/trunk/rhino-mocks/Rhino.Mocks/Constraints/AllPropertiesMatchConstraint.cs 

Olof Bjarnason

unread,
Jan 13, 2009, 7:39:05 AM1/13/09
to nunit-...@googlegroups.com
Isn't OSS great :)

If I read it correctly, it is recursive. It also handles IEnumarble
objects aswell as IComparable objects.

So it seems to be a good base for the more general ValueEquality, as
opposed to the ValueType equality.

Both seem to be of use for the NUnit community, right?


2009/1/13 Simone Busoli <simone...@gmail.com>:

Charlie Poole

unread,
Jan 13, 2009, 12:16:42 PM1/13/09
to nunit-...@googlegroups.com
If this is from MS.Net, please don't publish it here.

Among other things, examining the Microsoft source
means a person can't contribute to the Mono project.
And, of course, you may be violating your license.

It's up to you if you do it and fine to discuss
anything you learned, but just don't put it in front
of others.

If it's from Mono, that's OK, although Reflector
is unnecessary in that case - you can just look
at the source.

Charlie

> -----Original Message-----
> From: nunit-...@googlegroups.com
> [mailto:nunit-...@googlegroups.com] On Behalf Of Olof Bjarnason
> Sent: Tuesday, January 13, 2009 4:12 AM
> To: nunit-...@googlegroups.com
> Subject: [nunit-discuss] Re: Asserting that all public
> properties match
>
>

Olof Bjarnason

unread,
Jan 13, 2009, 12:25:05 PM1/13/09
to nunit-...@googlegroups.com
2009/1/13 Charlie Poole <cha...@nunit.com>:
>
> If this is from MS.Net, please don't publish it here.

I did not even think of this possibility - silly of me.

We can only hope the OSS movement keeps growing.

Charlie Poole

unread,
Jan 13, 2009, 4:50:18 PM1/13/09
to nunit-...@googlegroups.com
Hi Olof,

> 2009/1/13 Charlie Poole <cha...@nunit.com>:
> >
> > If this is from MS.Net, please don't publish it here.
>
> I did not even think of this possibility - silly of me.
>
> We can only hope the OSS movement keeps growing.

No problem, if it's not an issue you deal with all the time,
it's normal to not think about it.

Charlie
Reply all
Reply to author
Forward
0 new messages