让我们把你的优秀和最喜欢的扩展方法列一个列表。

要求是必须发布完整的代码,以及如何使用它的示例和解释。

基于对这个主题的高度兴趣,我在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 T ObjectWithMin<T, TResult>(this IEnumerable<T> sequence, Func<T, TResult> predicate)
    where T : class
    where TResult : IComparable
{
    if (!sequence.Any()) return null;

    //get the first object with its predicate value
    var seed = sequence.Select(x => new {Object = x, Value = predicate(x)}).FirstOrDefault();
    //compare against all others, replacing the accumulator with the lesser value
    //tie goes to first object found
    return
        sequence.Select(x => new {Object = x, Value = predicate(x)})
            .Aggregate(seed,(acc, x) => acc.Value.CompareTo(x.Value) <= 0 ? acc : x).Object;
}

public static T ObjectWithMax<T, TResult>(this IEnumerable<T> sequence, Func<T, TResult> predicate)
    where T : class
    where TResult : IComparable
{
    if (!sequence.Any()) return null;

    //get the first object with its predicate value
    var seed = sequence.Select(x => new {Object = x, Value = predicate(x)}).FirstOrDefault();
    //compare against all others, replacing the accumulator with the greater value
    //tie goes to last object found
    return
        sequence.Select(x => new {Object = x, Value = predicate(x)})
            .Aggregate(seed, (acc, x) => acc.Value.CompareTo(x.Value) > 0 ? acc : x).Object;
}

用法:

var myObject = myList.ObjectWithMin(x=>x.PropA);

这些方法基本上取代了像

var myObject = myList.OrderBy(x=>x.PropA).FirstOrDefault(); //O(nlog(n)) and unstable

and

var myObject = myList.Where(x=>x.PropA == myList.Min(x=>x.PropA)).FirstOrDefault(); //O(N^2) but stable

and

var minValue = myList.Min(x=>x.PropA);
var myObject = myList.Where(x=>x.PropA == minValue).FirstOrDefault(); //not a one-liner, and though linear and stable it's slower (evaluates the enumerable twice)

其他回答

一些用于使用列表的扩展:

/// <summary>
/// Wrap an object in a list
/// </summary>
public static IList<T> WrapInList<T>(this T item)
{
    List<T> result = new List<T>();
    result.Add(item);
    return result;
}

使用如:

myList = someObject.InList();

使IEnumerable包含来自一个或多个源的项,以使IEnumerable更像列表。对于高性能代码来说,这可能不是一个好主意,但对于测试来说很有用:

public static IEnumerable<T> Append<T>(this IEnumerable<T> enumerable, T newItem)
{
    foreach (T item in enumerable)
    {
        yield return item;
    }

    yield return newItem;
}

public static IEnumerable<T> Append<T>(this IEnumerable<T> enumerable, params T[] newItems)
{
    foreach (T item in enumerable)
    {
        yield return item;
    }

    foreach (T newItem in newItems)
    {
        yield return newItem;
    }
}

如使用。

someEnumeration = someEnumeration.Append(newItem);

还有其他可能的变化——例如。

someEnumeration = someEnumeration.Append(otherEnumeration);

如果你正在克隆项目,你可能还想克隆它们的列表:

public static IList<T> Clone<T>(this IEnumerable<T> source) where T: ICloneable
{
    List<T> result = new List<T>();

    foreach (T item in source)
    {
        result.Add((T)item.Clone());
    }

    return result;
}

当我使用ObservableCollection<T>时,我通常使用AddRange方法扩展它。这里的其他答案给出了这个的实现。

如果您愿意,可以将此代码放入Codeplex项目中。

下面是我们工作代码库中的一个有趣的例子。在作业线程上遍历一个昂贵的lazy-eval枚举对象,并通过一个可观察对象推回结果。

public static IObservable<T> ToAsyncObservable<T>(this IEnumerable<T> @this)
{
    return Observable.Create<T>(observer =>
    {
        var task = new Task(() =>
        {
            try
            {
                @this.Run(observer.OnNext);
                observer.OnCompleted();
            }
            catch (Exception e)
            {
                observer.OnError(e);
            }
        });

        task.Start();

        return () => { };
    });
}

愚蠢的示例:

new DirectoryInfo(@"c:\program files")
    .EnumerateFiles("*", SearchOption.AllDirectories)
    .ToAsyncObservable()
    .BufferWithTime(TimeSpan.FromSeconds(0.5))
    .ObserveOnDispatcher()
    .Subscribe(
        l => Console.WriteLine("{0} received", l.Count),
        () => Console.WriteLine("Done!"));

for (;;)
{
    Thread.Sleep(10);
    Dispatcher.PushFrame(new DispatcherFrame());
}

显然,这个扩展将是无用的,如果你不使用辉煌的响应式扩展!

感谢评论中的Richard,这个扩展方法是不必要的。RX已经有一个扩展方法“tooobservable”,它接受IScheduler。那就用这个吧!

我发现这个方法很有用

public static IEnumerable<T> EmptyIfNull<T>(this IEnumerable<T> pSeq)
{
    return pSeq ?? Enumerable.Empty<T>();
}

它在调用代码中删除空检查。现在你可以

MyList.EmptyIfNull().Where(....)

无论如何,把它放在codeplex项目中。

将对象序列化/反序列化为XML:

/// <summary>Serializes an object of type T in to an xml string</summary>
/// <typeparam name="T">Any class type</typeparam>
/// <param name="obj">Object to serialize</param>
/// <returns>A string that represents Xml, empty otherwise</returns>
public static string XmlSerialize<T>(this T obj) where T : class, new()
{
    if (obj == null) throw new ArgumentNullException("obj");

    var serializer = new XmlSerializer(typeof(T));
    using (var writer = new StringWriter())
    {
        serializer.Serialize(writer, obj);
        return writer.ToString();
    }
}

/// <summary>Deserializes an xml string in to an object of Type T</summary>
/// <typeparam name="T">Any class type</typeparam>
/// <param name="xml">Xml as string to deserialize from</param>
/// <returns>A new object of type T is successful, null if failed</returns>
public static T XmlDeserialize<T>(this string xml) where T : class, new()
{
    if (xml == null) throw new ArgumentNullException("xml");

    var serializer = new XmlSerializer(typeof(T));
    using (var reader = new StringReader(xml))
    {
        try { return (T)serializer.Deserialize(reader); }
        catch { return null; } // Could not be deserialized to this type.
    }
}

有几次我发现自己想要Groovy的“安全导航”之类的东西。

从http://groovy.codehaus.org/Statements:

如果你在行走一个复杂的物体 图和不想要的 你可以抛出nullpointerexception 使用?。操作员而不是。来 执行导航。 Def foo = null Def bar = .myMethod()断言条 = =零

那么,您认为为它添加扩展方法是一个好主意吗? 喜欢的东西:

obj.SafelyNavigate(x => x.SomeProperty.MaybeAMethod().AnotherProperty);

我认为即使它也会带来一些麻烦,这也很好。

如果你认为这是个好主意:

您认为值类型应该发生什么?, 返回默认吗?扔吗?,通过泛型约束禁用它? 吞咽NullReferenceException来实现它会太冒险吗?, 你有什么建议?, 遍历表达式树执行每个调用或成员访问似乎很困难,而且有点过度(如果可能的话),不是吗?

也许这只是一个坏主意:D,但我认为如果做得对,它是有用的。 如果没有类似的东西,你认为它有一些价值,我可能会给它一个机会,然后编辑答案。