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

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

基于对这个主题的高度兴趣,我在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上实现和单元测试。


当前回答

用于ienumables的ForEach

public static class FrameworkExtensions
{
    // a map function
    public static void ForEach<T>(this IEnumerable<T> @enum, Action<T> mapFunction)
    {
        foreach (var item in @enum) mapFunction(item);
    }
}

天真的例子:

var buttons = GetListOfButtons() as IEnumerable<Button>;

// click all buttons
buttons.ForEach(b => b.Click());

酷的例子:

// no need to type the same assignment 3 times, just
// new[] up an array and use foreach + lambda
// everything is properly inferred by csc :-)
new { itemA, itemB, itemC }
    .ForEach(item => {
        item.Number = 1;
        item.Str = "Hello World!";
    });

注意:

这与Select不同,因为Select期望函数返回转换为另一个列表的内容。

ForEach只是允许您为每个项执行一些东西,而不需要任何转换/数据操作。

我这样做,所以我可以在一个更函数式的风格编程,我很惊讶,列表有一个ForEach,而IEnumerable没有。

把这个放到codeplex项目中

其他回答

“请在你的答案上标记接受将代码放入Codeplex项目。”

为什么?这个网站上的所有东西都在CC-by-sa-2.5下,所以只要把你的扩展溢出项目放在相同的许可证下,你就可以自由使用它。

总之,这是一个字符串。逆函数,基于这个问题。

/// <summary>
/// Reverse a String
/// </summary>
/// <param name="input">The string to Reverse</param>
/// <returns>The reversed String</returns>
public static string Reverse(this string input)
{
    char[] array = input.ToCharArray();
    Array.Reverse(array);
    return new string(array);
}

我今天刚刚在博客上写了这个。它是INotifyPropertyChanged属性周围的强类型响应式包装器。

GetPropertyValues返回一个IObservable<T>的值,当它们改变时,从当前值开始。如果忽略当前值,可以对结果调用Skip(1)。

用法如下:

IObservable<int> values = viewModel.GetPropertyValues(x => x.IntProperty);

实现:

public static class NotifyPropertyChangeReactiveExtensions
{
    // Returns the values of property (an Expression) as they change, 
    // starting with the current value
    public static IObservable<TValue> GetPropertyValues<TSource, TValue>(
        this TSource source, Expression<Func<TSource, TValue>> property)
        where TSource : INotifyPropertyChanged
    {
        MemberExpression memberExpression = property.Body as MemberExpression;

        if (memberExpression == null)
        {
            throw new ArgumentException(
                "property must directly access a property of the source");
        }

        string propertyName = memberExpression.Member.Name;

        Func<TSource, TValue> accessor = property.Compile();

        return source.GetPropertyChangedEvents()
            .Where(x => x.EventArgs.PropertyName == propertyName)
            .Select(x => accessor(source))
            .StartWith(accessor(source));
    }

    // This is a wrapper around FromEvent(PropertyChanged)
    public static IObservable<IEvent<PropertyChangedEventArgs>>
        GetPropertyChangedEvents(this INotifyPropertyChanged source)
    {
        return Observable.FromEvent<PropertyChangedEventHandler, 
            PropertyChangedEventArgs>(
            h => new PropertyChangedEventHandler(h),
            h => source.PropertyChanged += h,
            h => source.PropertyChanged -= h);
    }
}

我写过无数的扩展方法,这里有几个我觉得特别有用的。请随意执行。

public static class ControlExtenders
{
    /// <summary>
    /// Advanced version of find control.
    /// </summary>
    /// <typeparam name="T">Type of control to find.</typeparam>
    /// <param name="id">Control id to find.</param>
    /// <returns>Control of given type.</returns>
    /// <remarks>
    /// If the control with the given id is not found
    /// a new control instance of the given type is returned.
    /// </remarks>
    public static T FindControl<T>(this Control control, string id) where T : Control
    {
        // User normal FindControl method to get the control
        Control _control = control.FindControl(id);

        // If control was found and is of the correct type we return it
        if (_control != null && _control is T)
        {
            // Return new control
            return (T)_control;
        }

        // Create new control instance
        _control = (T)Activator.CreateInstance(typeof(T));

        // Add control to source control so the
        // next it is found and the value can be
        // passed on itd, remember to hide it and
        // set an ID so it can be found next time
        if (!(_control is ExtenderControlBase))
        {
            _control.Visible = false;
        }
        _control.ID = id;
        control.Controls.Add(_control);

        // Use reflection to create a new instance of the control
        return (T)_control;
    }
}

public static class GenericListExtenders
{
    /// <summary>
    /// Sorts a generic list by items properties.
    /// </summary>
    /// <typeparam name="T">Type of collection.</typeparam>
    /// <param name="list">Generic list.</param>
    /// <param name="fieldName">Field to sort data on.</param>
    /// <param name="sortDirection">Sort direction.</param>
    /// <remarks>
    /// Use this method when a dinamyc sort field is requiered. If the 
    /// sorting field is known manual sorting might improve performance.
    /// </remarks>
    public static void SortObjects<T>(this List<T> list, string fieldName, SortDirection sortDirection)
    {
        PropertyInfo propInfo = typeof(T).GetProperty(fieldName);
        if (propInfo != null)
        {
            Comparison<T> compare = delegate(T a, T b)
            {
                bool asc = sortDirection == SortDirection.Ascending;
                object valueA = asc ? propInfo.GetValue(a, null) : propInfo.GetValue(b, null);
                object valueB = asc ? propInfo.GetValue(b, null) : propInfo.GetValue(a, null);
                return valueA is IComparable ? ((IComparable)valueA).CompareTo(valueB) : 0;
            };
            list.Sort(compare);
        }
    }

    /// <summary>
    /// Creates a pagged collection from generic list.
    /// </summary>
    /// <typeparam name="T">Type of collection.</typeparam>
    /// <param name="list">Generic list.</param>
    /// <param name="sortField">Field to sort data on.</param>
    /// <param name="sortDirection">Sort direction.</param>
    /// <param name="from">Page from item index.</param>
    /// <param name="to">Page to item index.</param>
    /// <param name="copy">Creates a copy and returns a new list instead of changing the current one.</param>
    /// <returns>Pagged list collection.</returns>
    public static List<T> Page<T>(this List<T> list, string sortField, bool sortDirection, int from, int to, bool copy)
    {
        List<T> _pageList = new List<T>();

        // Copy list
        if (copy)
        {
            T[] _arrList = new T[list.Count];
            list.CopyTo(_arrList);
            _pageList = new List<T>(_arrList);
        }
        else
        {
            _pageList = list;
        }

        // Make sure there are enough items in the list
        if (from > _pageList.Count)
        {
            int diff = Math.Abs(from - to);
            from = _pageList.Count - diff;
        }
        if (to > _pageList.Count)
        {
            to = _pageList.Count;
        }

        // Sort items
        if (!string.IsNullOrEmpty(sortField))
        {
            SortDirection sortDir = SortDirection.Descending;
            if (!sortDirection) sortDir = SortDirection.Ascending;
            _pageList.SortObjects(sortField, sortDir);
        }

        // Calculate max number of items per page
        int count = to - from;
        if (from + count > _pageList.Count) count -= (from + count) - _pageList.Count;

        // Get max number of items per page
        T[] pagged = new T[count];
        _pageList.CopyTo(from, pagged, 0, count);

        // Return pagged items
        return new List<T>(pagged);
    }

    /// <summary>
    /// Shuffle's list items.
    /// </summary>
    /// <typeparam name="T">List type.</typeparam>
    /// <param name="list">Generic list.</param>
    public static void Shuffle<T>(this List<T> list)
    {
        Random rng = new Random();
        for (int i = list.Count - 1; i > 0; i--)
        {
            int swapIndex = rng.Next(i + 1);
            if (swapIndex != i)
            {
                T tmp = list[swapIndex];
                list[swapIndex] = list[i];
                list[i] = tmp;
            }
        }
    }

    /// <summary>
    /// Converts generic List to DataTable.
    /// </summary>
    /// <typeparam name="T">Type.</typeparam>
    /// <param name="list">Generic list.</param>
    /// <param name="columns">Name of the columns to copy to the DataTable.</param>
    /// <returns>DataTable.</returns>
    public static DataTable ToDataTable<T>(this List<T> list, string[] columns)
    {
        List<string> _columns = new List<string>(columns);
        DataTable dt = new DataTable();

        foreach (PropertyInfo info in typeof(T).GetProperties())
        {
            if (_columns.Contains(info.Name) || columns == null)
            {
                dt.Columns.Add(new DataColumn(info.Name, info.PropertyType));
            }
        }
        foreach (T t in list)
        {
            DataRow row = dt.NewRow();
            foreach (PropertyInfo info in typeof(T).GetProperties())
            {
                if (_columns.Contains(info.Name) || columns == null)
                {
                    row[info.Name] = info.GetValue(t, null);
                }
            }
            dt.Rows.Add(row);
        }
        return dt;
    }
}

public static class DateTimeExtenders
{
    /// <summary>
    /// Returns number of month from a string representation.
    /// </summary>
    /// <returns>Number of month.</returns>
    public static int MonthToNumber(this DateTime datetime, string month)
    {
        month = month.ToLower();
        for (int i = 1; i <= 12; i++)
        {
            DateTime _dt = DateTime.Parse("1." + i + ".2000");
            string _month = CultureInfo.InvariantCulture.DateTimeFormat.GetMonthName(i).ToLower();
            if (_month == month)
            {
                return i;
            }
        }
        return 0;
    }

    /// <summary>
    /// Returns month name from month number.
    /// </summary>
    /// <returns>Name of month.</returns>
    public static string MonthToName(this DateTime datetime, int month)
    {
        for (int i = 1; i <= 12; i++)
        {
            if (i == month)
            {
                return CultureInfo.InvariantCulture.DateTimeFormat.GetMonthName(i);
            }
        }
        return "";
    }
}

public static class ObjectExtender
{
    public static object CloneBinary<T>(this T originalObject)
    {
        using (var stream = new System.IO.MemoryStream())
        {
            BinaryFormatter binaryFormatter = new BinaryFormatter();
            binaryFormatter.Serialize(stream, originalObject);
            stream.Position = 0;
            return (T)binaryFormatter.Deserialize(stream);
        }
    }

    public static object CloneObject(this object obj)
    {
        using (MemoryStream memStream = new MemoryStream())
        {
            BinaryFormatter binaryFormatter = new BinaryFormatter(null, new StreamingContext(StreamingContextStates.Clone));
            binaryFormatter.Serialize(memStream, obj);
            memStream.Position = 0;
            return binaryFormatter.Deserialize(memStream);
        }
    }
}

public static class StringExtenders
{
    /// <summary>
    /// Returns string as unit.
    /// </summary>
    /// <param name="value">Value.</param>
    /// <returns>Unit</returns>
    public static Unit ToUnit(this string value)
    {
        // Return empty unit
        if (string.IsNullOrEmpty(value))
            return Unit.Empty;

        // Trim value
        value = value.Trim();

        // Return pixel unit
        if (value.EndsWith("px"))
        {
            // Set unit type
            string _int = value.Replace("px", "");

            // Try parsing to int
            double _val = 0;
            if (!double.TryParse(_int, out _val))
            {
                // Invalid value
                return Unit.Empty;
            }

            // Return unit
            return new Unit(_val, UnitType.Pixel);
        }

        // Return percent unit
        if (value.EndsWith("%"))
        {
            // Set unit type
            string _int = value.Replace("%", "");

            // Try parsing to int
            double _val = 0;
            if (!double.TryParse(_int, out _val))
            {
                // Invalid value
                return Unit.Empty;
            }

            // Return unit
            return new Unit(_val, UnitType.Percentage);
        }

        // No match found
        return new Unit();
    }

    /// <summary>
    /// Returns alternative string if current string is null or empty.
    /// </summary>
    /// <param name="str"></param>
    /// <param name="alternative"></param>
    /// <returns></returns>
    public static string Alternative(this string str, string alternative)
    {
        if (string.IsNullOrEmpty(str)) return alternative;
        return str;
    }

    /// <summary>
    /// Removes all HTML tags from string.
    /// </summary>
    /// <param name="html">String containing HTML tags.</param>
    /// <returns>String with no HTML tags.</returns>
    public static string StripHTML(this string html)
    {
        string nohtml = Regex.Replace(html, "<(.|\n)*?>", "");
        nohtml = nohtml.Replace("\r\n", "").Replace("\n", "").Replace("&nbsp;", "").Trim();
        return nohtml;
    }
}

第一个是我最喜欢的,因为它可以代替:

Control c = this.FindControl("tbName");
if (c != null)
{
    // Do something with c
    customer.Name = ((TextBox)c).Text;
}

用这个:

TextBox c = this.FindControl<TextBox>("tbName");
customer.Name = c.Text;

设置默认字符串值:

string str = "";
if (string.IsNullOrEmpty(str))
{
    str = "I'm empty!";
}

就变成:

str = str.Alternative("I'm empty!");

一些工具IEnumerable: ToString(格式),ToString(函数)和Join(分隔符)。

例如:

var names = new[] { "Wagner", "Francine", "Arthur", "Bernardo" };

names.ToString("Name: {0}\n");
// Name: Wagner
// Name: Francine
// Name: Arthur
// Name: Bernardo

names.ToString(name => name.Length > 6 ? String.Format("{0} ", name) : String.Empty);
// Francine Bernardo

names.Join(" - ");
// Wagner - Francine - Arthur - Bernardo

扩展:

public static string ToString<T>(this IEnumerable<T> self, string format)
{
    return self.ToString(i => String.Format(format, i));
}

public static string ToString<T>(this IEnumerable<T> self, Func<T, object> function)
{
    var result = new StringBuilder();

    foreach (var item in self) result.Append(function(item));

    return result.ToString();
}

public static string Join<T>(this IEnumerable<T> self, string separator)
{
    return String.Join(separator, values: self.ToArray());
}

我觉得这个很有用:

public static class PaulaBean
{
    private static String paula = "Brillant";
    public static String GetPaula<T>(this T obj) {
        return paula;
    }
}

你可以在CodePlex上使用它。