.NET Forum / Languages / C# / February 2008
Compare 2 objects
|
|
Thread rating:  |
tshad - 27 Feb 2008 00:18 GMT 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
Marc Gravell - 27 Feb 2008 00:35 GMT > 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);
?
tshad - 27 Feb 2008 00:50 GMT >> int temp = delegate(ProjectTableName ptn1, ProjectTableName ptn2) >> {return ptn1.ProcessOrder.CompareTo(ptn2);}; [quoted text clipped - 6 lines] > > 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
Marc Gravell - 27 Feb 2008 07:02 GMT > 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); }
tshad - 27 Feb 2008 18:39 GMT >> 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... Are you saying that I should be doing it differently than:
ProjectTableName ptn1 = projectTables.Find(delegate(ProjectTableName ptn) {return ptn.TableName == "employee";});
>> 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! 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: [quoted text clipped - 19 lines] > 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
Marc Gravell - 28 Feb 2008 05:24 GMT > 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
tshad - 28 Feb 2008 21:15 GMT >> 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? 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
>> By the way, what is the "=>" for. > [quoted text clipped - 9 lines] > > Marc Marc Gravell - 29 Feb 2008 08:07 GMT 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)); }
Free MagazinesGet these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...
|
|
|