Let's start with Microsoft's documentation for IQueryable. It says:
IQueryable interface inherits the
IEnumerable interface so that if it represents a query, the results of that query can be enumerated. Enumeration causes the expression tree associated with an
IQueryable object to be executed. The definition of "executing an expression tree" is specific to a query provider. For example, it may involve translating the expression tree to an appropriate query language for the underlying data source.
In other words, an
IEnumerable represents a collection that can be enumerated, while an
IQueryable represents some sort of query that can be executed. Think of
IQueryable as a "state machine" of sorts; it doesn't actually do anything until you compel it to execute by calling
ToList() or something that enumerates its output. So you can build up an
IQueryable with successive Linq statements, and nothing will happen until you actually ask it for output.
I was looking over the C# version of the Specification Pattern on Wikipedia. It's hilariously verbose, given that all you really need is some lambda expressions:
var licenseHasNotExpired = license => license.ExpiryDate > DateTime.Now;
You can use Joseph Albahari's Predicate Builder to chain together your lambda expressions with AND and OR, and presto: you have a Specification Pattern. You can use it to build up an expression tree that gets executed when you need the answer to the questions that your rules answer.
If you use Expression Trees to do this, you can even run a Visitor over them to get log output.