Method to return a collection of objects, filtered by a string I have a Vehicle object which has a few properties such as Make, Model, Price, etc. 

I also have a VehicleCollection object which derives from List&lt;Vehicle which has a few custom methods, one of which is the following...

class VehicleCollection : List&lt;Vehicle&gt;
{
    public VehicleCollection GetVehicles(string _searchTerm = "")
    {
        // return the entire collection if no search term is provided
        if (_searchTerm.Length == 0)
            return this;

        var matchingVehicles = new VehicleCollection();
        foreach(var vehicle in this) // loop through all vehicles
        {
            PropertyInfo[] propInfos = vehicle.GetType().GetProperties(); // all properties of the current vehicle
            for (int i = 0; i &lt; propInfos.Length; i++)
            {
                var propVal = propInfos[i].GetValue(vehicle); // the value of the current property of the current vehicle

                // check aganst value of a strings or the values within a string array
                // ignores case
                if (propVal is string propertyValueStr &amp;&amp; propertyValueStr.IndexOf(_searchTerm, StringComparison.CurrentCultureIgnoreCase) &gt;= 0
                    || propVal is string[] propValueArr &amp;&amp; propValueArr.Any(x =&gt; x.IndexOf(_searchTerm, StringComparison.CurrentCultureIgnoreCase) &gt;= 0))
                {
                    matchingVehicles.Add(vehicle);
                }
            }
        }

        return matchingVehicles;
    }
}


This returns a collection of vehicles, of which each vehicle must have a property whose value contains the supplied _searchTerm parameter.

Is this the best way to do this? Can this be achieved using LINQ at all? Can this be done without reflection?

Edit:
At the request of a comment, here is the Vehicle Class, with a few unnecessary methods omitted. 

public class Vehicle
{
    public string ID { get; private set; }
    public string Make { get; private set; }
    public string Model { get; private set; }
    internal decimal Value { get; private set; }
    public string Price { get { return string.Format("{0:C}", Value); } }
    public VehicleColourEnum Colour { get; private set; }
    internal StatusEnum Status { get; private set; }
    public string State
    {
        get 
        {
            switch (Status)
            {
                case StatusEnum.ComingSoon:
                    return "Coming Soon";
                case StatusEnum.HasDeposit:
                    return "Has Deposit";
                case StatusEnum.InStock:
                    return "In Stock";
                case StatusEnum.Sold:
                    return "Sold";
                case StatusEnum.Unknown:
                default:
                    return "Unknown";
            }
        }
    }

    public Vehicle(string _make, string _model, decimal _value, VehicleColourEnum _colour = VehicleColourEnum.None, StatusEnum _status = StatusEnum.Unknown)
    {
        Make = _make;
        Model = _model;
        Value = _value;
        Colour = _colour;
        Status = _status;
        ID = Guid.NewGuid().ToString("N");
    }
}
I'll ignore your naming conventions/etc as I know that's not what you're asking about.

Since the VehicleCollection object already inherits from IEnumerable through the List&lt;> inheritence, you can query the collection as a list through the 'this' keyword.

That means you could write up your search method like:

public VehicleCollection GetVehicles(string searchTerm = "")
{
    // Null and white-space check for sanity
    if(string.IsNullOrWhiteSpace(searchTerm))
    // We're assuming if the search term is bad, we return everything. 
    // This isn't standard practice - usually we return nothing
        return this; 

    var matches = new VehicleCollection();
    matches.AddRange(
        this.Where(v=&gt;v.ID.Equals(searchTerm) || 
                    v.Make.Equals(searchTerm) || 
                    v.Model.Equals(searchTerm)
    // I personally prefer to be explicit in what I'm selecting, but it's your choice
        ).Select(v=&gt;v)); 

    // inline IF because I'm lazy
    // again, we're returning everything if there are no matches, 
    // which isn't standard practice.
    return matches.Any()? matches: this; 
}


Hope that helps!