tags:

views:

241

answers:

2

If one calls the .Max() extension method on an IEnumerable<T>, and the objects within do not implement IComparable, one gets System.ArgumentException: At least one object must implement IComparable.

Why don't Max and similar methods constrain T to implement IComparable, so that this problem can be caught at compile time instead of at run time?

+3  A: 

I guess because it's more flexible. For example, you may have an IEnumerable<object> which happens to contain strings, in which case Max() can be called quite safely on it, despite the fact that the type Object does not implement IComparable.

Matt Howells
A difficult aspect of many design problems is deciding how to balance the pain of a robust system with a burdensome requirement against the pain of a flexible system that can fail at runtime. In this particular case, the designers opted for flexibility over robustness; whether that was the _right_ choice is certainly debatable, but some choice had to be made and neither option was perfect.
Eric Lippert
@Eric: +1, but I wish you had posted an answer so I could accept it.
Matt Howells
+6  A: 

Comparisons are... fun. Firstly, you've got a choice of IComparable<T> or IComparable - which would you choose? Currently (via Comparer<T>.Default) it supports both, but there is no "this or that" generic constraint.

Then you get the issue of Nullable<T>; this has "lifted" comparisons, so whether it is comparable or not depends on the T; but again, Comparer<T>.Default deals with this for us (Nullable<T> implements neither IComparable nor IComparable<T>).

Plus; it saves on generic constraint propagation; as soon as you have a constraint like this in library code, it quickly infects all the upstream calling code, making it a hard slog.

Marc Gravell
An insightful answer. Gets my +1 for now, won't accept yet as I don't want to discourage other answers.
Matt Howells