让我们把你的优秀和最喜欢的扩展方法列一个列表。
要求是必须发布完整的代码,以及如何使用它的示例和解释。
基于对这个主题的高度兴趣,我在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 StringExtensions {
/// <summary>
/// Parses a string into an Enum
/// </summary>
/// <typeparam name="T">The type of the Enum</typeparam>
/// <param name="value">String value to parse</param>
/// <returns>The Enum corresponding to the stringExtensions</returns>
public static T EnumParse<T>(this string value) {
return StringExtensions.EnumParse<T>(value, false);
}
public static T EnumParse<T>(this string value, bool ignorecase) {
if (value == null) {
throw new ArgumentNullException("value");
}
value = value.Trim();
if (value.Length == 0) {
throw new ArgumentException("Must specify valid information for parsing in the string.", "value");
}
Type t = typeof(T);
if (!t.IsEnum) {
throw new ArgumentException("Type provided must be an Enum.", "T");
}
return (T)Enum.Parse(t, value, ignorecase);
}
}
将字符串解析为Enum很有用。
public enum TestEnum
{
Bar,
Test
}
public class Test
{
public void Test()
{
TestEnum foo = "Test".EnumParse<TestEnum>();
}
}
这要归功于斯科特·多尔曼
——编辑Codeplex项目——
我问过Scott Dorman,他是否介意我们在Codeplex项目中发布他的代码。我从他那里得到的回答是:
感谢你对SO帖子和CodePlex项目的提醒。我赞成你对这个问题的回答。是的,代码目前在CodeProject开放许可证(http://www.codeproject.com/info/cpol10.aspx)下有效地处于公共领域。
我没有问题,这被包括在CodePlex项目,如果你想把我添加到项目(用户名是sdorman),我会添加该方法加上一些额外的枚举助手方法。
ThrowIfArgumentIsNull是做空检查的好方法,我们都应该这样做。
public static class Extensions
{
public static void ThrowIfArgumentIsNull<T>(this T obj, string parameterName) where T : class
{
if (obj == null) throw new ArgumentNullException(parameterName + " not allowed to be null");
}
}
下面是使用它的方法,它适用于您的命名空间中的所有类或任何您使用该命名空间的地方。
internal class Test
{
public Test(string input1)
{
input1.ThrowIfArgumentIsNull("input1");
}
}
在CodePlex项目上使用这段代码是可以的。
没有检查整个线程,所以它可能已经在这里,但是:
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.
有几次我发现自己想要Groovy的“安全导航”之类的东西。
从http://groovy.codehaus.org/Statements:
如果你在行走一个复杂的物体
图和不想要的
你可以抛出nullpointerexception
使用?。操作员而不是。来
执行导航。
Def foo = null Def bar =
.myMethod()断言条
= =零
那么,您认为为它添加扩展方法是一个好主意吗?
喜欢的东西:
obj.SafelyNavigate(x => x.SomeProperty.MaybeAMethod().AnotherProperty);
我认为即使它也会带来一些麻烦,这也很好。
如果你认为这是个好主意:
您认为值类型应该发生什么?,
返回默认吗?扔吗?,通过泛型约束禁用它?
吞咽NullReferenceException来实现它会太冒险吗?,
你有什么建议?,
遍历表达式树执行每个调用或成员访问似乎很困难,而且有点过度(如果可能的话),不是吗?
也许这只是一个坏主意:D,但我认为如果做得对,它是有用的。
如果没有类似的东西,你认为它有一些价值,我可能会给它一个机会,然后编辑答案。
我喜欢下面这些方法来处理带有Flags属性集的枚举:
public static bool AnyOf(this object mask, object flags)
{
return ((int)mask & (int)flags) != 0;
}
public static bool AllOf(this object mask, object flags)
{
return ((int)mask & (int)flags) == (int)flags;
}
public static object SetOn(this object mask, object flags)
{
return (int)mask | (int)flags;
}
etc.
使用示例:
var options = SomeOptions.OptionA;
options = options.SetOn(OptionB);
options = options.SetOn(OptionC);
if (options.AnyOf(SomeOptions.OptionA | SomeOptions.OptionB))
{
etc.
原始方法来自本文:http://www.codeproject.com/KB/cs/masksandflags.aspx?display=Print
我只是把它们转换成扩展方法。
但它们的一个问题是对象类型的参数,这意味着所有对象最终都被这些方法扩展,而理想情况下,它们应该只应用于枚举。
更新
根据评论,你可以绕过“签名污染”,以牺牲性能为代价,如下所示:
public static bool AnyOf(this Enum mask, object flags)
{
return (Convert.ToInt642(mask) & (int)flags) != 0;
}