Compare 2 objects

T

tshad

I am trying to take part of my functions out of my Sort routine to do a
compare (as it does) where I just find out if object 1 is less then, equal
to or greater than object 2

I have the following:

ProjectTableName ptn1 = projectTables.Find(delegate(ProjectTableName ptn)
{return ptn.TableName == "employee";});
ProjectTableName ptn2 = projectTables.Find(delegate(ProjectTableName ptn)
{ return ptn.TableName == "customer"; });

int temp = delegate(ProjectTableName ptn1, ProjectTableName ptn2) {return
ptn1.ProcessOrder.CompareTo(ptn2);};

I am getting an error on the ptn1 and ptn2 in the last line that says:

A local variable named 'ptn1' cannot be declared in this scope because it
would give a different meaning to 'ptn1', which is already used in a 'parent
or current' scope to denote something else

The same for ptn2.

I am also getting an error:

Cannot convert anonymous method block to type 'int' because it is not a
delegate type

In the first 2 lines, I am trying to get a ProjectTableName object where the
TableName = "employee" and one that equals "customer".

Then I want to compare the objects using the ProcessOrder Property.

I want to eventually put the 2 Finds inside the last line to give me just
one line, but I was having similar problems so I tried to split it out first
just to get it to work.

How would I change this to make it work?

Thanks,

Tom
 
M

Marc Gravell

   int temp = delegate(ProjectTableName ptn1, ProjectTableName ptn2){return
ptn1.ProcessOrder.CompareTo(ptn2);};
...
Then I want to compare the objects using the ProcessOrder Property.

Forgetting the return type, this would define a delegate, not an
integer result - i.e. a Comparer<ProjectTableName>
Well, what is ProcessOrder? if it is IComparable[<T>] perhaps simply:

int tmp = ptn1.ProcessOrder.CompareTo(ptn2.ProcessOrder);

?
 
T

tshad

Marc said:
int temp = delegate(ProjectTableName ptn1, ProjectTableName ptn2)
{return ptn1.ProcessOrder.CompareTo(ptn2);};
...
Then I want to compare the objects using the ProcessOrder Property.

Forgetting the return type, this would define a delegate, not an
integer result - i.e. a Comparer<ProjectTableName>
Well, what is ProcessOrder? if it is IComparable[<T>] perhaps simply:

int tmp = ptn1.ProcessOrder.CompareTo(ptn2.ProcessOrder);

That was what I came up with also. And it works great.

But how do I do it in one statement? I assume I would use delegates that
would pass back the ProjectTableName.

ProjectTableName ptn1 = projectTables.Find(delegate(ProjectTableName ptn)
{return ptn.TableName == "employee";});
ProjectTableName ptn2 = projectTables.Find(delegate(ProjectTableName ptn)
{ return ptn.TableName == "customer"; });

int tmp = ptn1.ProcessOrder.CompareTo(ptn2.ProcessOrder);

Another wrinkle would be to make sure they are not null. Can I do that with
delegates?

Thanks,

Tom
 
M

Marc Gravell

But how do I do it in one statement?
Why do you need to? How would that help?
I assume I would use delegates that would pass back the ProjectTableName.
Find already does that...
Another wrinkle would be to make sure they are not null.
Is "ProcessOrder" the natural sequence? If so, you could make
ProjectTableName : IComparable<ProjectTableName>, and use
Comparer<ProjectTableName>.Deafult.Compare, which handles null...
otherwise just code it!

Unless you have an overriding necessity, you can get the single-
statement by simply refactoring the body into a helper method:

static void Main()
{
List<ProjectTableName> projectTables = new
List<ProjectTableName>();
int result = CompareByName(projectTables, "employee",
"customer");
}
public static int CompareByName(
List<ProjectTableName> tables,
string tableName1, string tableName2) {
var ptn1 = tables.Find(ptn => ptn.TableName ==
tableName1);
var ptn2 = tables.Find(ptn => ptn.TableName ==
tableName2);
// handle nulls (not found)
if(ReferenceEquals(ptn1,ptn2)) return 0;
if(ReferenceEquals(ptn1,null)) return -1;
if(ReferenceEquals(ptn2,null)) return 1;
return ptn1.ProcessOrder.CompareTo(ptn2.ProcessOrder);
}
 
T

tshad

Marc Gravell said:
Why do you need to? How would that help?

Find already does that...

Are you saying that I should be doing it differently than:

ProjectTableName ptn1 = projectTables.Find(delegate(ProjectTableName ptn)
{return ptn.TableName == "employee";});
Is "ProcessOrder" the natural sequence? If so, you could make
ProjectTableName : IComparable<ProjectTableName>, and use
Comparer<ProjectTableName>.Deafult.Compare, which handles null...
otherwise just code it!

ProcessOrder is just the order that a table has to inserted. I need to
track whether a key I am using is a foreign key to a parent table or to a
lookup table. If when I compare the ProcessOrder to the ProcessOrder of the
current table and I get a -1, am dealing with a Parent table, if a 1 then I
am dealing with a lookup table.

So what I am doing is getting the ProjectTableName object for the current
table name and one for the one I want to compare then compare the
ProcessOrder properties of each.

Doing it as I did works fine and handles the null possibility as I can do a
null test on both objects before actually doing the compare.

I was just looking to see how I would do it in one statement (if that was
even feasible). Not that I necessarily would but wanted to see what it
would entail and then decide which was the better way.
Unless you have an overriding necessity, you can get the single-
statement by simply refactoring the body into a helper method:

static void Main()
{
List<ProjectTableName> projectTables = new
List<ProjectTableName>();
int result = CompareByName(projectTables, "employee",
"customer");
}
public static int CompareByName(
List<ProjectTableName> tables,
string tableName1, string tableName2) {
var ptn1 = tables.Find(ptn => ptn.TableName ==
tableName1);
var ptn2 = tables.Find(ptn => ptn.TableName ==
tableName2);
// handle nulls (not found)
if(ReferenceEquals(ptn1,ptn2)) return 0;
if(ReferenceEquals(ptn1,null)) return -1;
if(ReferenceEquals(ptn2,null)) return 1;
return ptn1.ProcessOrder.CompareTo(ptn2.ProcessOrder);
}

That was what I was looking for. Just another way to do it.

If it was you, which would you do? The 2 statements to get the object,
test for null, then compare the objects. Or using your other method.

By the way, what is the "=>" for.

Thanks,

Tom
 
M

Marc Gravell

If it was you, which would you do?   The 2 statements to get the object,
test for null, then compare the objects.  Or using your other method.

Sorry, I'm confused; which 2 approaches are we comparing?
By the way, what is the "=>" for.

C# 3 lambda syntax:
Find(ptn => ptn.TableName == tableName2)
is the same as
Find(delegate (ProjectTableName ptn) {return ptn.TableName ==
tableName2;});

Note in particular that nothing we have removed is actually necessary
to understand the meaning; easier to understand without wading through
fluff

Marc
 
T

tshad

Marc said:
Sorry, I'm confused; which 2 approaches are we comparing?

The first method where you get the 2 ProjectTableName objects then compare
them
*****************************************************
int tmp;
ProjectTableName ptn1 = projectTables.Find(delegate(ProjectTableName ptn)
{return ptn.TableName == "employee";});
ProjectTableName ptn2 = projectTables.Find(delegate(ProjectTableName ptn)
{ return ptn.TableName == "customer"; });

if (ptn1 != null && pnt2 != null)
tmp = ptn1.ProcessOrder.CompareTo(ptn2.ProcessOrder);
else
do something
*********************************************************

VS

Your other method of using a helper method:
***********************************************************
static void Main()
{
List<ProjectTableName> projectTables = new
List<ProjectTableName>();
int result = CompareByName(projectTables, "employee",
"customer");
}
public static int CompareByName(
List<ProjectTableName> tables,
string tableName1, string tableName2) {
var ptn1 = tables.Find(ptn => ptn.TableName ==
tableName1);
var ptn2 = tables.Find(ptn => ptn.TableName ==
tableName2);
// handle nulls (not found)
if(ReferenceEquals(ptn1,ptn2)) return 0;
if(ReferenceEquals(ptn1,null)) return -1;
if(ReferenceEquals(ptn2,null)) return 1;
return ptn1.ProcessOrder.CompareTo(ptn2.ProcessOrder);
}
****************************************************

Thanks,

Tom
 
M

Marc Gravell

It depends entirely on how much I need to re-use ;-p

If the "find 2 rows [if they exist] by <x>, and compare by <y>" is quite
common, then perhaps (where "tables" is a List<ProjectTableName>):

int value = tables.Compare(ptn => ptn.TableName,
"Foo", "Bar", ptn => ptn.ProcessOrder);

using the extension method below [untested]... this locates the 2 rows with
TableName "Foo" and "Bar" respectively, and if they both exist uses the
standard comparison based on their ProcessOrder. If either or both is
missing, standard null rules apply.

Marc

static int Compare<TSource, TFindValue, TCompareValue>(this List<TSource>
source,
Func<TSource, TFindValue> findSelector, TFindValue x, TFindValue y,
Func<TSource, TCompareValue> compareSelector) where TSource : class
{
EqualityComparer<TFindValue> findComparer =
EqualityComparer<TFindValue>.Default;
TSource xItem = source.Find(item =>
findComparer.Equals(findSelector(item), x)),
yItem = source.Find(item =>
findComparer.Equals(findSelector(item), y));
if (ReferenceEquals(x, y)) return 0;
if (ReferenceEquals(x, null)) return -1;
if (ReferenceEquals(y, null)) return 1;
return
Comparer<TCompareValue>.Default.Compare(compareSelector(xItem),
compareSelector(yItem));
}
 

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

Similar Threads


Top