Go Premium for a chance to win a PS4. Enter to Win

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 309
  • Last Modified:

sorting a list with linq myList.Sort(r => r.CompareTo(myobj));

Hi there;

I have a question regarding in linq in C# for sorting a list.

I have a function foo;

void foo(AAA myobj)
{
...

myList.Sort(r => r.CompareTo(myobj));
}

Please let me say I implement the CompareTo method of IComparable<MyClass>.

public int CompareTo(MyClass m) is the signiture of the implemented comparator.

but it gives an error, so could you tell me what is the problem?

Kind regards.
0
jazzIIIlove
Asked:
jazzIIIlove
  • 7
  • 6
1 Solution
 
theHollowCommented:
Hello
How did you implement the "CompareTo" method?
Did you add the method alone, or did you also inherit the "IComparable<MyClass>" interface as well?
Because you will have to do that.

If your list is a "IEnumerable<MyClass>", you can also sort a list by doing this:

items = from i in items 
            orderby i.SomeProperty descending, i.SomOtherProperty ascending
            select i;

Open in new window


Hope it helped :-)
0
 
effesCommented:
Try
myList.Sort((x,y) => x.CompareTo(y));

Open in new window

The Sort method expects you to pass it a Comparison delegate, i.e. something that represents a method that takes two objects of a given type as parameters and compares them. (See http://msdn.microsoft.com/en-us/library/w56d4y5z.aspx and http://msdn.microsoft.com/en-us/library/tfakywbh.aspx for reference.)
0
 
jazzIIIloveAuthor Commented:
Hi,

@thehollow:
Please let me say I implement the CompareTo method of IComparable<MyClass>.

public int CompareTo(MyClass m) is the signiture of the implemented comparator. So it takes 1 parameter, not 2. I cannot change my CompareTo function.
@effes:
Your code is not working as It takes to params. myList.Sort((x,y) => x.CompareTo(y));
0
Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

 
jazzIIIloveAuthor Commented:
Not to but two :)
0
 
effesCommented:
What doesn't work / what error(s) do you get?

My code has two parameters because the Sort method needs them. Internally it takes two elements from your list and runs it through the compare method it is provided. The call to your CompareTo method is just the same as it is in the code you provided: Take an object of the MyClass class and call its CompareTo method, passing it another object of type MyClass as parameter (the only one).
I don't see why this shouldn't work.

Maybe I misunderstood your question?
0
 
jazzIIIloveAuthor Commented:
Ok, let me give more detail:
[Serializable]
Class A : IComparable
{

int CompareTo(Class A otherObj)
{
}

}

Class B
{

void AFunc(Class A myObj)
{

//MyList here
//your code here?

}

Is it like that?

Thanks for your patience.

Kind regards.
}
0
 
effesCommented:
As long as myList is a List<ClassA> it should work.
0
 
effesCommented:
It just occurred to me that since your class implements IComparable<MyClass> it enough to use the Sort method without parameters. It will use your CompareTo method automatically. So in this case
myList.Sort((x,y) => x.CompareTo(y));

Open in new window

and
myList.Sort();

Open in new window

should give you the same result.

Sorry, I was kinda fixated on the first one.
0
 
jazzIIIloveAuthor Commented:
So, Sort without params is OK even i implemenyed CompareTo function of IComparable Interface? I want to use CompareTo function as i implemented already.

Kind regards.
0
 
effesCommented:
Using Sort without parameters is OK because you implemented IComparable,
Sort will check whether the type it has to sort implements that interface. If it does, Sort will use the corresponding CompareTo method. So your CompareTo will be called autmatically.
You can check that by setting a breakpoint inside CompareTo.
0
 
jazzIIIloveAuthor Commented:
ok, just to populate;

When I write this:
Class A
{
public int DoThis(Class B b)
{
myList.Sort((r, b) => r.CompareTo(b));
}

}

I have the following error:
Error      2      A local variable named 'b' cannot be declared in this scope because it would give a different meaning to 'b', which is already used in a 'parent or current' scope to denote something else      

I got it Sort without params it works but I want to use the incoming parameter but failed...

Regards.
0
 
effesCommented:
The lambda expression that you pass to the Sort method ("(r, b) => r.CompareTo(b)") is just an anonymous function. In your case it says: this is a function that takes two parameters, one named "r" and one named "b". The problem with this is that the name "b" is already in use by the parameter of the DoThis method.
You would have to rename "b" to "c" or something ("(r, c) => r.CompareTo(b)"). You can still call CompareTo with "b", but calling Sort like that will almost certainly fail, because the results returned by CompareTo are inconsistent.

What are you trying to achieve when you use the incoming parameter?
0
 
jazzIIIloveAuthor Commented:
Aha...So lambda expressions cannot use input parameters of a function?

And i always get confused that anonymous function. I mean i don't declare 'r' but using it. How? What is the logic there?

Kind regards.
0
 
effesCommented:
What's happening is this: The lambda expression is an anonymous function. On the left side of the lambda operator (the "=>") you specifiy the input parameters for the function. That's like declaring new variables whose scope is just the body of the lambda expression (the part to the right of the lambda operator). The only one who can pass values to those parameters is the "caller" of the expression (in your case the Sort method).
Inside the body of the expression you have access to the parameters you defined and to all variables in whose scope the expression is declared.
So in your case you have access to the input parameter "b" of the outer method "DoThis" and the input parameter "b" of the lambda expression. The compiler has no way of knowing which one of the b's you actually mean.

Now, if you rename the second parameter of the lambda eypression from "b" to "c" ("(r, c) => r.CompareTo(b)") to avoid the ambiguity, the code will compile. The problem begins when the Sort method kicks in: it will take two elements in the list and pass it to the lambda expression, because it wants to know how they compare. Inside the lambda expression they are accessible via the input parameters "r" and "c". But the lambda expression only takes the first element ("r") and compares it to an element from outside the scope of the lambda expression ("b"). "c" is completely ignored. The Sort method calls the lamba expression again and again with new combinations of elements in the list, until the are in the right order. Since the lambda expression never compares the two elements that are passed to it, but only the first one to a fixed element ("b" never changes as long as Sort runs), Sort will at some point consider the results inconsistent and throw an exception (this is done to prevent it from running endlessly).

That's why I asked what you are trying to achieve. It would make it easier to tweak things to work better for you.
0

Featured Post

[Webinar] Cloud and Mobile-First Strategy

Maybe you’ve fully adopted the cloud since the beginning. Or maybe you started with on-prem resources but are pursuing a “cloud and mobile first” strategy. Getting to that end state has its challenges. Discover how to build out a 100% cloud and mobile IT strategy in this webinar.

  • 7
  • 6
Tackle projects and never again get stuck behind a technical roadblock.
Join Now