Best Way In C# To Sort A List

Best Way To Sort A List Banner Image

Introduction

Sorting data is important to organize the data in both a visual representation and organizing for logical based reasons in the code. It may come from a database, from user inputs, and automatically generated files to parse. Most of the time it is unorganized data, and it is best to sort it. C# comes with build functionality for sorting single objects and even more complex objects many times. We'll look at List Sort and also LINQ's order by and analyze the speed, readability, conciseness, and memory impact.

LINQ's Order By Sort Method

In C#, LINQ provides a convenient way to sort the data in ascending order(called order by) or descending order(called order by desc) options. Even better it allows you to select which property in the class you would like to sort by.

Order by descending for numerical values will order from largest value to smallest value. While order by for numerical values will order by smallest to largest values.

Order by descending for string values will order from Z to A and order by will be from A to Z.

LINQ's Order By Sort Method Code Example
List<Car> carList = new List<Car>();//Can hold multple car objects
carList.Add(new Car(383958943, "blue", 4, "MakeT", "SuperM", 2014));//Add a new Car to the list
carList.Add(new Car(435435123, "white", 4, "MakeT", "CrossOver", 2017));//Add a new Car to the list
carList.Add(new Car(934904823, "red", 4, "MakeH", "Suv", 2022));//Add a new Car to the list
carList.Add(new Car(950348549, "gray", 4, "MakeF", "Truck", 2020));//Add a new Car to the list
carList.Add(new Car(309483049, "black", 4, "MakeB", "Compact", 2019));//Add a new Car to the list
Console.WriteLine($"VIN Number Order by Descending");//Print message to the screen
foreach (Car car in carList.OrderByDescending(x => x.VinNumber))//loop through each of the values in order of largest to smallest
{
    Console.WriteLine($"VinNumber:{car.VinNumber}, Color:{car.Color}, DoorNumber:{car.DoorNumber}, Make:{car.Make}, Model:{car.Model}, Year:{car.Year}");//Print the value to the console
}
Console.WriteLine($"");//Print blank space to screen
Console.WriteLine($"VIN Number Order by");//Print message to the screen
foreach (Car car in carList.OrderBy(x => x.VinNumber))//loop through each of the values in order of smallest to largest
{
    Console.WriteLine($"VinNumber:{car.VinNumber}, Color:{car.Color}, DoorNumber:{car.DoorNumber}, Make:{car.Make}, Model:{car.Model}, Year:{car.Year}");//Print the value to the console
}
Console.WriteLine($"");//Print blank space to screen
Console.WriteLine($"");//Print blank space to screen
Console.WriteLine($"Make Order by Descending");//Print message to the screen
foreach (Car car in carList.OrderByDescending(x => x.Make))//loop through each of the values in order of largest to smallest
{
    Console.WriteLine($"VinNumber:{car.VinNumber}, Color:{car.Color}, DoorNumber:{car.DoorNumber}, Make:{car.Make}, Model:{car.Model}, Year:{car.Year}");//Print the value to the console
}
Console.WriteLine($"");//Print blank space to screen
Console.WriteLine($"Make Order by ");//Print message to the screen
foreach (Car car in carList.OrderBy(x => x.Make))//loop through each of the values in order of smallest to largest
{
    Console.WriteLine($"VinNumber:{car.VinNumber}, Color:{car.Color}, DoorNumber:{car.DoorNumber}, Make:{car.Make}, Model:{car.Model}, Year:{car.Year}");//Print the value to the console
}
public class Car
{
    public Car(int vinNumber, string color, int doorNumber, string make, string model, int year)
    {
        VinNumber = vinNumber;
        Color = color;
        DoorNumber = doorNumber;
        Make = make;
        Model = model;
        Year = year;
    }
    public int VinNumber { get; set; }
    public string Color { get; set; }
    public int DoorNumber { get; set; }
    public string Make { get; set; }
    public string Model { get; set; }
    public int Year { get; set; }
}
Code Output
VIN Number Order by Descending
VinNumber:950348549, Color:gray, DoorNumber:4, Make:MakeF, Model:Truck, Year:2020
VinNumber:934904823, Color:red, DoorNumber:4, Make:MakeH, Model:Suv, Year:2022
VinNumber:435435123, Color:white, DoorNumber:4, Make:MakeT, Model:CrossOver, Year:2017
VinNumber:383958943, Color:blue, DoorNumber:4, Make:MakeT, Model:SuperM, Year:2014
VinNumber:309483049, Color:black, DoorNumber:4, Make:MakeB, Model:Compact, Year:2019

VIN Number Order by
VinNumber:309483049, Color:black, DoorNumber:4, Make:MakeB, Model:Compact, Year:2019
VinNumber:383958943, Color:blue, DoorNumber:4, Make:MakeT, Model:SuperM, Year:2014
VinNumber:435435123, Color:white, DoorNumber:4, Make:MakeT, Model:CrossOver, Year:2017
VinNumber:934904823, Color:red, DoorNumber:4, Make:MakeH, Model:Suv, Year:2022
VinNumber:950348549, Color:gray, DoorNumber:4, Make:MakeF, Model:Truck, Year:2020


Make Order by Descending
VinNumber:383958943, Color:blue, DoorNumber:4, Make:MakeT, Model:SuperM, Year:2014
VinNumber:435435123, Color:white, DoorNumber:4, Make:MakeT, Model:CrossOver, Year:2017
VinNumber:934904823, Color:red, DoorNumber:4, Make:MakeH, Model:Suv, Year:2022
VinNumber:950348549, Color:gray, DoorNumber:4, Make:MakeF, Model:Truck, Year:2020
VinNumber:309483049, Color:black, DoorNumber:4, Make:MakeB, Model:Compact, Year:2019

Make Order by
VinNumber:309483049, Color:black, DoorNumber:4, Make:MakeB, Model:Compact, Year:2019
VinNumber:950348549, Color:gray, DoorNumber:4, Make:MakeF, Model:Truck, Year:2020
VinNumber:934904823, Color:red, DoorNumber:4, Make:MakeH, Model:Suv, Year:2022
VinNumber:383958943, Color:blue, DoorNumber:4, Make:MakeT, Model:SuperM, Year:2014
VinNumber:435435123, Color:white, DoorNumber:4, Make:MakeT, Model:CrossOver, Year:2017
LINQ's Order By Sort Speed Test

Next, we want to test the performance. For this test, there will be a list with one hundred thousand random objects. The list will be sorted one thousand times. This will be run ten times to get the average amount of times. Next, examine the code and see the result.

LINQ's Order By Sort Speed Test Example Code
using System.Diagnostics;
int numberOfTests = 10;//Number of tests 
List<double> testSpeedList = new List<double>();
for (int i = 0; i < numberOfTests; i++)
{
    testSpeedList.Add(LINQOrderBySpeedTest());
}
Console.WriteLine($"LINQ Order By Average speed:{Math.Round(testSpeedList.Average())}ms, In {numberOfTests} tests");
double LINQOrderBySpeedTest()
{
    int numberOfFunctionCalls = 1000;//Number of function calls made
    List<Car> carList = new List<Car>();//Can hold multple car objects
    int numberOfObjectsToCreate = 100000;
    int maxNumberOfVinNumber = 999999999;
    int maxNumberOfColorCharacters = 4;
    int maxNumberofWheels = 4;
    int maxNumberOfMakeCharacters = 10;
    int maxNumberOfModelCharacters = 10;
    int maxNumberOfYear = 4;
    for (int i = 0; i < numberOfObjectsToCreate; i++)
    {
        carList.Add(new Car(GetRandomInt(maxNumberOfVinNumber), GetRandomText(maxNumberOfColorCharacters), GetRandomInt(maxNumberofWheels), GetRandomText(maxNumberOfMakeCharacters), GetRandomText(maxNumberOfModelCharacters), GetRandomInt(maxNumberOfYear)));//Add a new Car to the list
    }
    Stopwatch stopwatch = new Stopwatch();
    stopwatch.Start();//Start the Stopwatch timer
    List<Car> orderCarList = new List<Car>();
    for (int i = 0; i < numberOfFunctionCalls; i++)
    {
        orderCarList = carList.OrderBy(x => x.VinNumber).ToList();//Sort the list
    }
    stopwatch.Stop();//Stop the Stopwatch timer
    Console.WriteLine($"Function calls:{numberOfFunctionCalls}, In {stopwatch.Elapsed.Minutes}m {stopwatch.Elapsed.Seconds}s {stopwatch.Elapsed.Milliseconds}ms");
    return stopwatch.Elapsed.TotalMilliseconds;
}
Supporting Code
int GetRandomInt(int maxNumber)
{
    Random random = new Random();
    int randomInt = random.Next(maxNumber); ;
    return randomInt;
}
string GetRandomText(int numberOfCharacters)
{
    string finalOutput = "";
    string alphbet = "abcedfghijklmnopqrstuvwxyz";
    for (int i = 0; i < numberOfCharacters; i++)
    {
        int randomIndex = GetRandomInt(alphbet.Length - 1);
        finalOutput += alphbet[randomIndex];
    }
    return finalOutput;
}
public class Car
{
    public Car(int vinNumber, string color, int doorNumber, string make, string model, int year)
    {
        VinNumber = vinNumber;
        Color = color;
        DoorNumber = doorNumber;
        Make = make;
        Model = model;
        Year = year;
    }
    public int VinNumber { get; set; }
    public string Color { get; set; }
    public int DoorNumber { get; set; }
    public string Make { get; set; }
    public string Model { get; set; }
    public int Year { get; set; }
}
Code Output
Function calls:1000, In 0m 13s 744ms
Function calls:1000, In 0m 13s 189ms
Function calls:1000, In 0m 13s 299ms
Function calls:1000, In 0m 13s 144ms
Function calls:1000, In 0m 13s 74ms
Function calls:1000, In 0m 12s 886ms
Function calls:1000, In 0m 13s 29ms
Function calls:1000, In 0m 12s 951ms
Function calls:1000, In 0m 13s 484ms
Function calls:1000, In 0m 13s 393ms
LINQ Order By Average speed:13220ms, In 10 tests

As you can see LINQ's order by gives us a baseline of about 13 seconds. We'll see how this compares to the other sorting methods.

LINQ's Order By Primary and Secondary Key Sort Method

Another advantage to the LINQ sorting method is that it can sort by a primary and secondary key. This is helpful if there are duplicates in the primary key and then sorting on a secondary key would help to add additional order. See below code example.

LINQ's Order By Primary and Secondary Key Sort Method Code Example
List<Car> carList = new List<Car>();//Can hold multiple car objects
carList.Add(new Car(383958943, "blue", 4, "MakeT", "SuperM", 2014));//Add a new Car to the list
carList.Add(new Car(435435123, "white", 4, "MakeT", "CrossOver", 2017));//Add a new Car to the list
carList.Add(new Car(934904823, "red", 4, "MakeH", "Suv", 2022));//Add a new Car to the list
carList.Add(new Car(950348549, "gray", 4, "MakeH", "Truck", 2020));//Add a new Car to the list
carList.Add(new Car(309483049, "black", 4, "MakeH", "Compact", 2019));//Add a new Car to the list
Console.WriteLine($"Make Order by Descending then order by descending on Model");//Print message to the screen
foreach (Car car in carList.OrderByDescending(x => x.Make).ThenByDescending(y => y.Model))//loop through each of the values in order of largest to smallest then by order by descending of secondary key
{
    Console.WriteLine($"VinNumber:{car.VinNumber}, Color:{car.Color}, DoorNumber:{car.DoorNumber}, Make:{car.Make}, Model:{car.Model}, Year:{car.Year}");//Print the value to the console
}
Console.WriteLine($"");//Print blank space to screen
Console.WriteLine($"Make Order by then order by on Model");//Print message to the screen
foreach (Car car in carList.OrderBy(x => x.Make).ThenBy(y => y.Model))//loop through each of the values in order of smallest to largest then order by of secondary key
{
    Console.WriteLine($"VinNumber:{car.VinNumber}, Color:{car.Color}, DoorNumber:{car.DoorNumber}, Make:{car.Make}, Model:{car.Model}, Year:{car.Year}");//Print the value to the console
}
Supporting Code
public class Car
{
    public Car(int vinNumber, string color, int doorNumber, string make, string model, int year)
    {
        VinNumber = vinNumber;
        Color = color;
        DoorNumber = doorNumber;
        Make = make;
        Model = model;
        Year = year;
    }
    public int VinNumber { get; set; }
    public string Color { get; set; }
    public int DoorNumber { get; set; }
    public string Make { get; set; }
    public string Model { get; set; }
    public int Year { get; set; }
}
Code Output
Make Order by Descending then order by descending on Model
VinNumber:383958943, Color:blue, DoorNumber:4, Make:MakeT, Model:SuperM, Year:2014
VinNumber:435435123, Color:white, DoorNumber:4, Make:MakeT, Model:CrossOver, Year:2017
VinNumber:950348549, Color:gray, DoorNumber:4, Make:MakeH, Model:Truck, Year:2020
VinNumber:934904823, Color:red, DoorNumber:4, Make:MakeH, Model:Suv, Year:2022
VinNumber:309483049, Color:black, DoorNumber:4, Make:MakeH, Model:Compact, Year:2019

Make Order by then order by on Model
VinNumber:309483049, Color:black, DoorNumber:4, Make:MakeH, Model:Compact, Year:2019
VinNumber:934904823, Color:red, DoorNumber:4, Make:MakeH, Model:Suv, Year:2022
VinNumber:950348549, Color:gray, DoorNumber:4, Make:MakeH, Model:Truck, Year:2020
VinNumber:435435123, Color:white, DoorNumber:4, Make:MakeT, Model:CrossOver, Year:2017
VinNumber:383958943, Color:blue, DoorNumber:4, Make:MakeT, Model:SuperM, Year:2014
LINQ's Order By Primary and Secondary Key Sort Method Speed Test

Next, we'll test the speed of this method. We would expect it to be slower than the original order by function but how much is the question. Let's look at the code and see.

LINQ's Order By Primary and Secondary Key Sort Method Speed Code
using System.Diagnostics;
int numberOfTests = 10;//Number of tests 
List<double> testSpeedList = new List<double>();
for (int i = 0; i < numberOfTests; i++)
{
    testSpeedList.Add(LINQOrderByPrimaryAndSecondaryKeySpeedTest());
}
Console.WriteLine($"LINQ Order By Primary and Secondary Key Average speed:{Math.Round(testSpeedList.Average())}ms, In {numberOfTests} tests");
double LINQOrderByPrimaryAndSecondaryKeySpeedTest()
{
    int numberOfFunctionCalls = 1000;//Number of function calls made
    List<Car> carList = new List<Car>();//Can hold multiple car objects
    int numberOfObjectsToCreate = 100000;
    int maxNumberOfVinNumber = 999999999;
    int maxNumberOfColorCharacters = 4;
    int maxNumberofWheels = 4;
    int maxNumberOfMakeCharacters = 10;
    int maxNumberOfModelCharacters = 10;
    int maxNumberOfYear = 4;
    for (int i = 0; i < numberOfObjectsToCreate; i++)
    {
        carList.Add(new Car(GetRandomInt(maxNumberOfVinNumber), GetRandomText(maxNumberOfColorCharacters), GetRandomInt(maxNumberofWheels), GetRandomText(maxNumberOfMakeCharacters), GetRandomText(maxNumberOfModelCharacters), GetRandomInt(maxNumberOfYear)));//Add a new Car to the list
    }
    Stopwatch stopwatch = new Stopwatch();
    stopwatch.Start();//Start the Stopwatch timer
    List<Car> orderCarList = new List<Car>();
    for (int i = 0; i < numberOfFunctionCalls; i++)
    {
        orderCarList = carList.OrderBy(x => x.VinNumber).ThenBy(y => y.Model).ToList();//Sort the list
    }
    stopwatch.Stop();//Stop the Stopwatch timer
    Console.WriteLine($"Function calls:{numberOfFunctionCalls}, In {stopwatch.Elapsed.Minutes}m {stopwatch.Elapsed.Seconds}s {stopwatch.Elapsed.Milliseconds}ms");
    return stopwatch.Elapsed.TotalMilliseconds;
}
Supporting Code
int GetRandomInt(int maxNumber)
{
    Random random = new Random();
    int randomInt = random.Next(maxNumber); ;
    return randomInt;
}
string GetRandomText(int numberOfCharacters)
{
    string finalOutput = "";
    string alphbet = "abcedfghijklmnopqrstuvwxyz";
    for (int i = 0; i < numberOfCharacters; i++)
    {
        int randomIndex = GetRandomInt(alphbet.Length - 1);
        finalOutput += alphbet[randomIndex];
    }
    return finalOutput;
}
public class Car
{
    public Car(int vinNumber, string color, int doorNumber, string make, string model, int year)
    {
        VinNumber = vinNumber;
        Color = color;
        DoorNumber = doorNumber;
        Make = make;
        Model = model;
        Year = year;
    }
    public int VinNumber { get; set; }
    public string Color { get; set; }
    public int DoorNumber { get; set; }
    public string Make { get; set; }
    public string Model { get; set; }
    public int Year { get; set; }
}
Code Output
Function calls:1000, In 0m 14s 489ms
Function calls:1000, In 0m 14s 44ms
Function calls:1000, In 0m 14s 260ms
Function calls:1000, In 0m 13s 988ms
Function calls:1000, In 0m 13s 857ms
Function calls:1000, In 0m 14s 26ms
Function calls:1000, In 0m 13s 965ms
Function calls:1000, In 0m 14s 9ms
Function calls:1000, In 0m 14s 212ms
Function calls:1000, In 0m 13s 991ms
LINQ Order By Primary and Secondary Key Average speed:14085ms, In 10 tests

List Sort Method

The next method is a build into the list function. It requires some setup in the class object for this work. In the class, it needs to be extended on an IComparable. This gives you greater control over how want the list to be sorted. Also, list sort doesn't create any new list but it reorders the existing list in memory. This is different than LINQ's order by function as that creates a new list in memory and returns a new list. The following example orders the VINs in ascending order. Examine the code below.

List Sort Method Code Example
List<Car> carList = new List<Car>();//Can hold multple car objects
carList.Add(new Car(383958943, "blue", 4, "MakeT", "SuperM", 2014));//Add a new Car to the list
carList.Add(new Car(435435123, "white", 4, "MakeT", "CrossOver", 2017));//Add a new Car to the list
carList.Add(new Car(934904823, "red", 4, "MakeH", "Suv", 2022));//Add a new Car to the list
carList.Add(new Car(950348549, "gray", 4, "MakeF", "Truck", 2020));//Add a new Car to the list
carList.Add(new Car(309483049, "black", 4, "MakeB", "Compact", 2019));//Add a new Car to the list
carList.Sort();//Sort items using the based on IComparable on the object itself
foreach (Car car in carList)//loop through each of the values
{
    Console.WriteLine($"VinNumber:{car.VinNumber}, Color:{car.Color}, DoorNumber:{car.DoorNumber}, Make:{car.Make}, Model:{car.Model}, Year:{car.Year}");//Print the value to the console
}
public class Car : IComparable<Car>
{
    public Car(int vinNumber, string color, int doorNumber, string make, string model, int year)
    {
        VinNumber = vinNumber;
        Color = color;
        DoorNumber = doorNumber;
        Make = make;
        Model = model;
        Year = year;
    }
    public int VinNumber { get; set; }
    public string Color { get; set; }
    public int DoorNumber { get; set; }
    public string Make { get; set; }
    public string Model { get; set; }
    public int Year { get; set; }
    public int CompareTo(Car? other)//sets to ascending order
    {
        if (other == null)
        {
            return 1;
        }
        else if (this.VinNumber < other.VinNumber)
        {
            return -1;
        }
        else if (this.VinNumber > other.VinNumber)
        {
            return 1;
        }
        else
        {
            return 0;
        }
    }
}
Code Output
VinNumber:309483049, Color:black, DoorNumber:4, Make:MakeB, Model:Compact, Year:2019
VinNumber:383958943, Color:blue, DoorNumber:4, Make:MakeT, Model:SuperM, Year:2014
VinNumber:435435123, Color:white, DoorNumber:4, Make:MakeT, Model:CrossOver, Year:2017
VinNumber:934904823, Color:red, DoorNumber:4, Make:MakeH, Model:Suv, Year:2022
VinNumber:950348549, Color:gray, DoorNumber:4, Make:MakeF, Model:Truck, Year:2020
List Sort Method Speed Test

Let's now test the list sort method. This will be the same test as the previous example.

using System.Diagnostics;
int numberOfTests = 10;//Number of tests 
List<double> testSpeedList = new List<double>();
for (int i = 0; i < numberOfTests; i++)
{
    testSpeedList.Add(ListSortKeySpeedTest());
}
Console.WriteLine($"List Sort Average speed:{Math.Round(testSpeedList.Average())}ms, In {numberOfTests} tests");
double ListSortKeySpeedTest()
{
    List<Car> carList = new List<Car>();//Can hold multiple car objects
    int numberOfObjectsToCreate = 100000;
    int maxNumberOfVinNumber = 999999999;
    int maxNumberOfColorCharacters = 4;
    int maxNumberofWheels = 4;
    int maxNumberOfMakeCharacters = 10;
    int maxNumberOfModelCharacters = 10;
    int maxNumberOfYear = 4;
    for (int i = 0; i < numberOfObjectsToCreate; i++)
    {
        carList.Add(new Car(GetRandomInt(maxNumberOfVinNumber), GetRandomText(maxNumberOfColorCharacters), GetRandomInt(maxNumberofWheels), GetRandomText(maxNumberOfMakeCharacters), GetRandomText(maxNumberOfModelCharacters), GetRandomInt(maxNumberOfYear)));//Add a new Car to the list
    }
    int numberOfFunctionCalls = 1000;//Number of function calls made
    Stopwatch stopwatch = new Stopwatch();
    stopwatch.Start();//Start the Stopwatch timer
    List<Car> orderCarList = new List<Car>();
    for (int i = 0; i < numberOfFunctionCalls; i++)
    {
        carList.Sort();
    }
    stopwatch.Stop();//Stop the Stopwatch timer
    Console.WriteLine($"Function calls:{numberOfFunctionCalls}, In {stopwatch.Elapsed.Minutes}m {stopwatch.Elapsed.Seconds}s {stopwatch.Elapsed.Milliseconds}ms");
    return stopwatch.Elapsed.TotalMilliseconds;
}
Supporting Code
int GetRandomInt(int maxNumber)
{
    Random random = new Random();
    int randomInt = random.Next(maxNumber); ;
    return randomInt;
}
string GetRandomText(int numberOfCharacters)
{
    string finalOutput = "";
    string alphbet = "abcedfghijklmnopqrstuvwxyz";
    for (int i = 0; i < numberOfCharacters; i++)
    {
        int randomIndex = GetRandomInt(alphbet.Length - 1);
        finalOutput += alphbet[randomIndex];
    }
    return finalOutput;
}
public class Car : IComparable<Car>
{
    public Car(int vinNumber, string color, int doorNumber, string make, string model, int year)
    {
        VinNumber = vinNumber;
        Color = color;
        DoorNumber = doorNumber;
        Make = make;
        Model = model;
        Year = year;
    }
    public int VinNumber { get; set; }
    public string Color { get; set; }
    public int DoorNumber { get; set; }
    public string Make { get; set; }
    public string Model { get; set; }
    public int Year { get; set; }
    public int CompareTo(Car? other)//sets to ascending order
    {
        if (other == null)
        {
            return 1;
        }
        else if (this.VinNumber < other.VinNumber)
        {
            return -1;
        }
        else if (this.VinNumber > other.VinNumber)
        {
            return 1;
        }
        else
        {
            return 0;
        }
    }
}
Code Output
Function calls:1000, In 0m 17s 989ms
Function calls:1000, In 0m 17s 695ms
Function calls:1000, In 0m 18s 101ms
Function calls:1000, In 0m 18s 540ms
Function calls:1000, In 0m 17s 913ms
Function calls:1000, In 0m 19s 463ms
Function calls:1000, In 0m 18s 517ms
Function calls:1000, In 0m 20s 311ms
Function calls:1000, In 0m 18s 895ms
Function calls:1000, In 0m 17s 976ms
List Sort Average speed:18541ms, In 10 tests

Conclusion

Overall RankMethodSpeedConciseReadability(1-5)Memory Consumption (1-5)
1LINQ's Order By Sort13220ms1 line44
2LINQ's Order By Primary and Secondary Key Sort14085ms1 line44
3List's Sort18541ms20 lines21

The best sorting method in C# is LINQ's order by function. It is the fastest method, it is compact by taking up only one line of code. It is also easy to read, but it does consume memory as it returns a new list. For the vast majority of use cases, this will serve your proposes. The second best method is again by LINQ and if you have a second key that you want to sort with then this also is a good method. The third best is the list's sort method. It has a more complicated setup and is the slowest of all the methods, but if you have a more complicated sort that needs to be done and involves more than 2 columns then this would be the best custom way to go.

Get Latest Updates
Comments Section