Overloading the && and || operators

A couple months ago I posted about our query API along with an explanation of how it works.  Our query API allows us to express our queries using strongly typed C# syntax:

List<Customer> customers = repository.FindAll(Customer.Columns.Age == 20 & Customer.Columns.Name == “foo”);

One of the things I pointed out in my previous posts was that I couldn’t overload the && and || operators directly since the framework doesn’t allow such craziness…at least not directly.

In particular, it is not possible to overload member access, method invocation, or the =, &&, ||, ?:, checked, unchecked, new, typeof, as, and is operators.
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/csspec/html/vclrfcsharpspec_7_2_2.asp

Over the last month I’ve done a little investigation on the topic to see if and how I can get && and || to behave the way I want.  This evening I came across the Conditional logical operators page on MSDN which gave me the answer I was looking for:

  • The operation x && y is evaluated as T.false(x) ? x : T.&(x, y), where T.false(x) is an invocation of the operator false declared in T, and T.&(x, y) is an invocation of the selected operator &. In other words, x is first evaluated and operator false is invoked on the result to determine if x is definitely false. Then, if x is definitely false, the result of the operation is the value previously computed for x. Otherwise, y is evaluated, and the selected operator & is invoked on the value previously computed for x and the value computed for y to produce the result of the operation.
  • The operation x || y is evaluated as T.true(x) ? x : T.|(x, y), where T.true(x) is an invocation of the operator true declared in T, and T.|(x, y) is an invocation of the selected operator |. In other words, x is first evaluated and operator true is invoked on the result to determine if x is definitely true. Then, if x is definitely true, the result of the operation is the value previously computed for x. Otherwise, y is evaluated, and the selected operator | is invoked on the value previously computed for x and the value computed for y to produce the result of the operation.

Since we already have the & and | operators in place it was simply a matter of overloading the true and false operators to both return false.  This results in the & and | operators always being called which in turn results in the two criteria objects being turned into an AndCriteria/OrCriteria! 

So now we can express our criteria expressions using the && and || syntax we’re accustomed to.

repository.FindAll(Customer.Columns.Age == 20 && Customer.Columns.Name == “foo”);

repository.FindAll(Customer.Columns.FirstName == “Foo” || Customer.Columns.LastName == “Bar”);

The relevant operator overloads are shown below.

public static bool operator true(Criteria<T> criteria) {
  
return false;
}

public static bool operator false(Criteria<T> criteria) {
  
return false;
}

public static Criteria<T> operator &(Criteria<T> lhs, Criteria<T> rhs) {
  
return new AndCriteria<T>(lhs, rhs);
}

public static Criteria<T> operator |(Criteria<T> lhs, Criteria<T> rhs) {
  
return new OrCriteria<T>(lhs, rhs);
}

# re: Overloading the && and || operators

Tuesday, July 18, 2006 12:29 AM by Liang    
Steve,

In OJB .NET (now DomainObjects), there has a class, QueryFacade, which take a criteria object. Maybe it can give you some idea how to design Query API. BTW, your posts are very interesting!

# re: Overloading the && and || operators

Tuesday, July 18, 2006 9:00 AM by Steve    
Liang,

Thanks! I'll have to take a look at the QueryFacade class to see if there are any new ideas that I can "borrow" :)

Post a Comment

 
 
Prove you're not a spammer: 
2 + 3 =