using System.Collections.Generic;
public static void Main()
var objects = new MyObject[]{
new MyObject() { Id = 9, SentBy = admin, InReplyTo = null, Level = 0, ShouldBe = 0, Message = "top level message #1" },
new MyObject() { Id = 10, SentBy = dealer, InReplyTo = 9, Level = 1, ShouldBe = 1, Message = "reply to top level message #1" },
new MyObject() { Id = 5, SentBy = admin, InReplyTo = null, Level = 0, ShouldBe = 2, Message = "top level message #2 (REPLY UNDER top level #1)" },
new MyObject() { Id = 6, SentBy = dealer, InReplyTo = 5, Level = 1, ShouldBe = 3, Message = "reply to top level message #2" },
new MyObject() { Id = 8, SentBy = dealer, InReplyTo = 5, Level = 1, ShouldBe = 4, Message = "reply 2 to top level message #2" },
new MyObject() { Id = 1, SentBy = admin, InReplyTo = null, Level = 0, ShouldBe = 5, Message = "top level message #4 (REPLY UNDER top level #1)" },
new MyObject() { Id = 3, SentBy = dealer, InReplyTo = 1, Level = 1, ShouldBe = 6, Message = "reply to top level message #4" },
new MyObject() { Id = 2, SentBy = rep, InReplyTo = null, Level = 0, ShouldBe = 7, Message = "top level message #3" },
new MyObject() { Id = 4, SentBy = dealer, InReplyTo = 2, Level = 1, ShouldBe = 8, Message = "reply to top level message #3" },
new MyObject() { Id = 7, SentBy = dealer, InReplyTo = 2, Level = 1, ShouldBe = 9, Message = "reply 2 to top level message #3" },
var threads = (from m in objects
let replies = objects.Where(o => o.InReplyTo == m.Id).OrderBy(o => o.Id)
var groups = from thread in threads
group thread by thread.TopMessage.SentBy into g
orderby g.First().TopMessage.Id descending
var sorted = groups.SelectMany(g => g.ToArray());
foreach(var item in sorted) {
Console.WriteLine(item.TopMessage.ShouldBe);
foreach(var subitem in item.Replies) {
Console.WriteLine(subitem.ShouldBe);
public int Id { get; set;}
public int SentBy {get;set;}
public int? InReplyTo {get;set;}
public int Level {get;set;}
public int ShouldBe {get;set;}
public string Message {get;set;}