让我们把你的优秀和最喜欢的扩展方法列一个列表。
要求是必须发布完整的代码,以及如何使用它的示例和解释。
基于对这个主题的高度兴趣,我在Codeplex上建立了一个名为extensionoverflow的开源项目。
请将您的回答标记为接受,以便将代码放入Codeplex项目。
请张贴完整的源代码,而不是一个链接。
Codeplex上新闻:
24.08.2010 Codeplex页面现在在这里:http://extensionoverflow.codeplex.com/
11.11.2008 XmlSerialize / XmlDeserialize现在是实现和单元测试。
11.11.2008仍有发展空间。;-)现在就加入!
11.11.2008第三位贡献者加入了ExtensionOverflow,欢迎加入BKristensen
11.11.2008 FormatWith现在是实现和单元测试。
09.11.2008第二个贡献者加入ExtensionOverflow。欢迎来到chakrit。
我们需要更多的开发人员。: -)
09.11.2008 ThrowIfArgumentIsNull现已在Codeplex上实现和单元测试。
我不想添加任何已经说过的东西,所以这里有一些我没有提到的东西。(如果这太长了,对不起):
public static class MyExtensions
{
public static bool IsInteger(this string input)
{
int temp;
return int.TryParse(input, out temp);
}
public static bool IsDecimal(this string input)
{
decimal temp;
return decimal.TryParse(input, out temp);
}
public static int ToInteger(this string input, int defaultValue)
{
int temp;
return (int.TryParse(input, out temp)) ? temp : defaultValue;
}
public static decimal ToDecimal(this string input, decimal defaultValue)
{
decimal temp;
return (decimal.TryParse(input, out temp)) ? temp : defaultValue;
}
public static DateTime ToFirstOfTheMonth(this DateTime input)
{
return input.Date.AddDays(-1 * input.Day + 1);
}
// Intentionally returns 0 if the target date is before the input date.
public static int MonthsUntil(this DateTime input, DateTime targetDate)
{
input = input.ToFirstOfTheMonth();
targetDate = targetDate.ToFirstOfTheMonth();
int result = 0;
while (input < targetDate)
{
input = input.AddMonths(1);
result++;
}
return result;
}
// Used for backwards compatibility in a system built before my time.
public static DataTable ToDataTable(this IEnumerable input)
{
// too much code to show here right now...
}
}
这是我今天刚创建的一个。
// requires .NET 4
public static TReturn NullOr<TIn, TReturn>(this TIn obj, Func<TIn, TReturn> func,
TReturn elseValue = default(TReturn)) where TIn : class
{ return obj != null ? func(obj) : elseValue; }
// versions for CLR 2, which doesn't support optional params
public static TReturn NullOr<TIn, TReturn>(this TIn obj, Func<TIn, TReturn> func,
TReturn elseValue) where TIn : class
{ return obj != null ? func(obj) : elseValue; }
public static TReturn NullOr<TIn, TReturn>(this TIn obj, Func<TIn, TReturn> func)
where TIn : class
{ return obj != null ? func(obj) : default(TReturn); }
它让你这样做:
var lname = thingy.NullOr(t => t.Name).NullOr(n => n.ToLower());
哪个比这个更流畅,(依我看)更容易阅读:
var lname = (thingy != null ? thingy.Name : null) != null
? thingy.Name.ToLower() : null;
我还没有看到任何关于这个问题的答案…
public static string[] Split(this string value, string regexPattern)
{
return value.Split(regexPattern, RegexOptions.None);
}
public static string[] Split(this string value, string regexPattern,
RegexOptions options)
{
return Regex.Split(value, regexPattern, options);
}
用法:
var obj = "test1,test2,test3";
string[] arrays = obj.Split(",");
还有一点:
public enum ParseFailBehavior
{
ReturnNull,
ReturnDefault,
ThrowException
}
public static T? ParseNullableEnum<T>(this string theValue, ParseFailBehavior desiredBehavior = ParseFailBehavior.ReturnNull) where T:struct
{
T output;
T? result = Enum.TryParse<T>(theValue, out output)
? (T?)output
: desiredBehavior == ParseFailBehavior.ReturnDefault
? (T?)default(T)
: null;
if(result == null && desiredBehavior == ParseFailBehavior.ThrowException)
throw new ArgumentException("Parse Failed for value {0} of enum type {1}".
FormatWith(theValue, typeof(T).Name));
}
这个版本需要。net 4.0;在3.5中你没有TryParse和可选参数;你就只能使用enumel . parse(),你必须尝试捕获它。它在3.5中仍然是完全可行的(而且更有用,因为enumel . parse()是oogly的,也是你唯一的其他选择):
public static T? ParseNummableEnum<T>(this string theValue)
{
return theValue.ParseNullableEnum<T>(ParseFailBehavior.ReturnNull);
}
public static T? ParseNullableEnum<T>(this string theValue,
ParseFailBehavior desiredBehavior) where T:struct
{
try
{
return (T?) Enum.Parse(typeof (T), theValue);
}
catch (Exception)
{
if(desiredBehavior == ParseFailBehavior.ThrowException) throw;
}
return desiredBehavior == ParseFailBehavior.ReturnDefault ? (T?)default(T) : null;
}
用法:
//returns null if OptionOne isn't an enum constant
var myEnum = "OptionOne".ParseNullableEnum<OptionEnum>();
//guarantees a return value IF the enum has a "zero" constant value (generally a good practice)
var myEnum = "OptionTwo".ParseNullableEnum<OptionEnum>(ParseFailBehavior.ReturnDefault).Value
没有检查整个线程,所以它可能已经在这里,但是:
public static class FluentOrderingExtensions
public class FluentOrderer<T> : IEnumerable<T>
{
internal List<Comparison<T>> Comparers = new List<Comparison<T>>();
internal IEnumerable<T> Source;
public FluentOrderer(IEnumerable<T> source)
{
Source = source;
}
#region Implementation of IEnumerable
public IEnumerator<T> GetEnumerator()
{
var workingArray = Source.ToArray();
Array.Sort(workingArray, IterativeComparison);
foreach(var element in workingArray) yield return element;
}
private int IterativeComparison(T a, T b)
{
foreach (var comparer in Comparers)
{
var result = comparer(a,b);
if(result != 0) return result;
}
return 0;
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
#endregion
}
public static FluentOrderer<T> OrderFluentlyBy<T,TResult>(this IEnumerable<T> source, Func<T,TResult> predicate)
where TResult : IComparable<TResult>
{
var result = new FluentOrderer<T>(source);
result.Comparers.Add((a,b)=>predicate(a).CompareTo(predicate(b)));
return result;
}
public static FluentOrderer<T> OrderFluentlyByDescending<T,TResult>(this IEnumerable<T> source, Func<T,TResult> predicate)
where TResult : IComparable<TResult>
{
var result = new FluentOrderer<T>(source);
result.Comparers.Add((a,b)=>predicate(a).CompareTo(predicate(b)) * -1);
return result;
}
public static FluentOrderer<T> ThenBy<T, TResult>(this FluentOrderer<T> source, Func<T, TResult> predicate)
where TResult : IComparable<TResult>
{
source.Comparers.Add((a, b) => predicate(a).CompareTo(predicate(b)));
return source;
}
public static FluentOrderer<T> ThenByDescending<T, TResult>(this FluentOrderer<T> source, Func<T, TResult> predicate)
where TResult : IComparable<TResult>
{
source.Comparers.Add((a, b) => predicate(a).CompareTo(predicate(b)) * -1);
return source;
}
}
用法:
var myFluentlyOrderedList = GetABunchOfComplexObjects()
.OrderFluentlyBy(x=>x.PropertyA)
.ThenByDescending(x=>x.PropertyB)
.ThenBy(x=>x.SomeMethod())
.ThenBy(x=>SomeOtherMethodAppliedTo(x))
.ToList();
... 当然,假设所有的谓词都返回与自身icomcomparable的类型。如果使用像MergeSort这样的稳定排序,而不是。net内置的快速排序,它会更好地工作,但它提供了类似于SQL的可读多字段排序能力(无论如何,它是方法链所能获得的最接近的功能)。您可以通过定义重载来接受比较lambda,而不是基于谓词创建它,从而扩展它以容纳非IComparable的成员。
EDIT: A little explanation, since the commenter got some upticks: this set of methods improves upon the basic OrderBy() functionality by allowing you to sort based on multiple fields in descending order of importance. A real-world example would be sorting a list of invoices by customer, then by invoice number (or invoice date). Other methods of getting the data in this order either wouldn't work (OrderBy() uses an unstable sort, so it cannot be chained) or would be inefficient and not look like it does what you're trying to do.