Custom Comparison at the object
1) 


    if (CompareDelegate == null || motorcycle2 == null)
    {
        throw new ArgumentNullException();
    }



This exception is misleading. First, it does not specify which parameter is null. Second, strictly speaking CompareDelegate is not a parameter. 

2) I would set the default value for CompareDefault:

public Comparison&lt;Motorcycle&gt; CompareDefault { get; set; } = 
    other =&gt; Name.CompareTo(other.Name);


this way you can probably remove some of the null checks and simplify CompareTo implementation.

3) Overall, I don't like this approach.


it scales poorly.
it hides comparison logic: there is no way to learn how two objects are going to be compared just by reading the code, the comparison logic is hidden inside some delegate.
most importantly, you break asymmetric property of comparison. If a.CompareTo(b) &gt; 0 then I expect that b.CompareTo(a) &lt; 0. But it is not the case, since nothing in your code prevents two objects from using different delegates for comparison. This alone looks like a huge source of problems to me.


IMHO, just write a bunch of regular IComparer&lt;T&gt; implementations and be done with it. It has none of the problems I mentioned above:

//custom comparers are implemented as stand alone classes, 
//they are not part of Motorcycle class.
public class Motorcycle
{
    public string Name { get; }
    public int Speed { get; set; }
    public int Price { get; set; }

    public Motorcycle(string name, int price, int speed)
    {
        Name = name;
        Price = price;
        Speed = speed;
    }
}

//It also guarantees asymmetry:
//if SpeedComparer.Compare(a,b) &lt; 0 then SpeedComparer.Compare(b,a) &gt; 0 is also true
class SpeedComparer : IComparer&lt;Motorcycle&gt;
{
    public int Compare(Motorcycle first, Motorcycle second)
    {
        //add null checks

        return first.Price.CompareTo(second.Price);
    }
}

class NameComparer : IComparer&lt;Motorcycle&gt;
{
    public int Compare(Motorcycle first, Motorcycle second)
    {
        //add null checks

        return first.Name.CompareTo(other.Name);
    }
}


Usage:

public void Test()
{
    var motorcycle1 = new Motorcycle("harley", 1000, 120);
    var motorcycle2 = new Motorcycle("yamaha", 1900, 130);
    var motorcycle3 = new Motorcycle("susuki", 1800, 150);
    var motorcycles = new List&lt;Motorcycle&gt;() { motorcycle1, motorcycle2, motorcycle3 };

    IComparer&lt;Motorcycle&gt; selectedComparer = new NameComparer();
    //compares by name
    TestComparison();

    selectedComparer = new SpeedComparer();
    //selectedComparer is changed, so now speeds are compared
    TestComparison();

    void TestComparison()
    {
        Debug.WriteLine($"Using {selectedComparer.GetType().Name}...");
        Debug.WriteLine(selectedComparer.Compare(motorcycle1, motorcycle2));
        motorcycles.Sort(selectedComparer);
        motorcycles.ForEach(m =&gt; Debug.WriteLine($"name {m.Name}   price {m.Price}   speed {m.Speed}"));
    }
}