} // end method private static object FindExtreme(IEnumerable enumerable, ref SystemTool.Comparison comparison, bool max) { object extreme = null; var isDefaultComparison = comparison == SystemTool.Comparison.Default; // indicates if the original comparsion value is Default var isEverDefault = false; // indicates if any comparison is ever Default var isEverNumeric = false; // indicates if any comparison is ever Numeric var isFirst = true; // flag for processing the first item in enumerable var isStringCheckDone = false; // flag for indicating if all the items in enumerable were checked for String comparison // Loop through all the items in enumerable. If comparison is either String // or Numeric, just perform the comparison, look at the result and set extreme // if necessary. For Default comparisons, special logic is necessary (see // comment for isDefaultComparison if statement below). foreach (var item in enumerable) { if (isFirst) { isFirst = false; extreme = item; continue; } // end if // (Non-Default comparisons are easy. Just perform the comparison. // For Default, perform the check and then examine the comparison // value afterwards. If its String, just return FindExtreme passing // comparison of String. If its Default, make note that a Default // comparison was used by setting isEverDefault to true; // If its numeric, make note that a Numeric comparison was used // by setting isEverNumeric to true. Then, if it hasn't already // been done (via isStingCheckDone), compare all the values // to the number 0 with a Default comparison to see if any rely // on a String comparison. If they do, just return FindExtreme // passing comparison of String. If no String comparisons occur, // then either Default only or Numeric only comparisons are safe. int compResult; if (isDefaultComparison) { comparison = SystemTool.Comparison.Default; compResult = item.CompareTo(extreme, ref comparison); if (comparison == SystemTool.Comparison.String) return FindExtreme(enumerable, ref comparison, max); if (comparison == SystemTool.Comparison.Default) isEverDefault = true; if (comparison == SystemTool.Comparison.Numeric) { isEverNumeric = true; if (!isStringCheckDone) { foreach (var e in enumerable) { comparison = SystemTool.Comparison.Default; e.CompareTo(0, ref comparison); if (comparison == SystemTool.Comparison.String) return FindExtreme(enumerable, ref comparison, max); } // end foreach isStringCheckDone = true; } // end if } // end if } else compResult = item.CompareTo(extreme, ref comparison); if (max && compResult > 0 || !max && compResult < 0) extreme = item; } // end foreach // At this point, there are no String comparisons. At this point, // if there was ever a Default comparison and also a Numeric comparison, // it is necessary to repeat FindExtreme call but this time with // an explicit Numeric comparison in case mixed objects that are Comparable // (Default comparison) do not compare the same way numerically. if (isEverNumeric && isEverDefault) { comparison = SystemTool.Comparison.Numeric; return FindExtreme(enumerable, ref comparison, max); } // end if return extreme; } // end method
} // end method public static object FindMin(this IEnumerable enumerable, ref SystemTool.Comparison comparison) { return FindExtreme(enumerable, ref comparison, false); } // end method