你见过的扩展方法最好或最有趣的用途是什么?

时间:2022-09-20 19:45:16

I'm starting to really love extension methods... I was wondering if anyone her has stumbled upon one that really blew their mind, or just found clever.

我开始非常喜欢延伸方法......我想知道是否有人偶然发现了一个真正引起他们注意的人,或者只是发现了聪明。

An example I wrote today:

我今天写的一个例子:

Edited due to other users' comments:

由于其他用户的评论而编辑:

public static IEnumerable<int> To(this int fromNumber, int toNumber) {    while (fromNumber < toNumber) {        yield return fromNumber;        fromNumber++;    }}

This allows a for loop to be written as a foreach loop:

这允许将for循环写为foreach循环:

foreach (int x in 0.To(16)) {    Console.WriteLine(Math.Pow(2, x).ToString());}

I can't wait to see other examples! Enjoy!

我迫不及待想看其他例子!请享用!

40 个解决方案

#1


The full solution is too large to put here, but I wrote a series of extension methods that would allow you to easily convert a DataTable into a CSV.

完整的解决方案太大了,不能放在这里,但我写了一系列扩展方法,可以让你轻松地将DataTable转换为CSV。

public static String ToCSV(this DataTable dataTable){    return dataTable.ToCSV(null, COMMA, true);}  public static String ToCSV(this DataTable dataTable, String qualifier){    return dataTable.ToCSV(qualifier, COMMA, true);}private static String ToCSV(this DataTable dataTable, String qualifier, String delimiter, Boolean includeColumnNames){    if (dataTable == null) return null;    if (qualifier == delimiter)    {        throw new InvalidOperationException(            "The qualifier and the delimiter are identical. This will cause the CSV to have collisions that might result in data being parsed incorrectly by another program.");    }    var sbCSV = new StringBuilder();    var delimiterToUse = delimiter ?? COMMA;    if (includeColumnNames)         sbCSV.AppendLine(dataTable.Columns.GetHeaderLine(qualifier, delimiterToUse));    foreach (DataRow row in dataTable.Rows)    {        sbCSV.AppendLine(row.ToCSVLine(qualifier, delimiterToUse));    }    return sbCSV.Length > 0 ? sbCSV.ToString() : null;}private static String ToCSVLine(this DataRow dataRow, String qualifier, String delimiter){    var colCount = dataRow.Table.Columns.Count;    var rowValues = new String[colCount];    for (var i = 0; i < colCount; i++)    {        rowValues[i] = dataRow[i].Qualify(qualifier);    }    return String.Join(delimiter, rowValues);}private static String GetHeaderLine(this DataColumnCollection columns, String qualifier, String delimiter){    var colCount = columns.Count;    var colNames = new String[colCount];    for (var i = 0; i < colCount; i++)    {        colNames[i] = columns[i].ColumnName.Qualify(qualifier);    }    return String.Join(delimiter, colNames);}private static String Qualify(this Object target, String qualifier){    return qualifier + target + qualifier;}

At the end of the day, you could call it like this:

在一天结束时,您可以这样称呼它:

someDataTable.ToCSV(); //Plain old CSVsomeDataTable.ToCSV("\""); //Double quote qualifiersomeDataTable.ToCSV("\"", "\t"); //Tab delimited

#2


This is one that's been getting some play from me lately:

这是最近一直在玩我的游戏:

public static IDisposable Tag(this HtmlHelper html, string tagName){    if (html == null)        throw new ArgumentNullException("html");    Action<string> a = tag => html.Write(String.Format(tag, tagName));    a("<{0}>");    return new Memento(() => a("</{0}>"));}

Used like:

using (Html.Tag("ul")){    this.Model.ForEach(item => using(Html.Tag("li")) Html.Write(item));    using(Html.Tag("li")) Html.Write("new");}

Memento is a handy class:

纪念品是一个方便的课程:

public sealed class Memento : IDisposable{    private bool Disposed { get; set; }    private Action Action { get; set; }    public Memento(Action action)    {        if (action == null)            throw new ArgumentNullException("action");        Action = action;    }    void IDisposable.Dispose()    {        if (Disposed)            throw new ObjectDisposedException("Memento");        Disposed = true;        Action();    }}

And to complete the dependencies:

并完成依赖:

public static void Write(this HtmlHelper html, string content){    if (html == null)        throw new ArgumentNullException("html");    html.ViewContext.HttpContext.Response.Write(content);}

#3


I'm not a fan of the INotifyPropertyChanged interface requiring that property names are passed as strings. I want a strongly-typed way to check at compile time that I'm only raising and handling property changes for properties that exist. I use this code to do that:

我不是INotifyPropertyChanged接口的粉丝,要求将属性名称作为字符串传递。我想要一种强类型的方法在编译时检查我只是为现有的属性提出并处理属性更改。我使用这段代码来做到这一点:

public static class INotifyPropertyChangedExtensions{    public static string ToPropertyName<T>(this Expression<Func<T>> @this)    {        var @return = string.Empty;        if (@this != null)        {            var memberExpression = @this.Body as MemberExpression;            if (memberExpression != null)            {                @return = memberExpression.Member.Name;            }        }        return @return;    }}

In classes that implement INotifyPropertyChanged I include this helper method:

在实现INotifyPropertyChanged的类中,我包含了这个帮助器方法:

protected void NotifySetProperty<T>(ref T field, T value,    Expression<Func<T>> propertyExpression){    if (field == null ? value != null : !field.Equals(value))    {        field = value;        this.NotifyPropertyChanged(propertyExpression.ToPropertyName());    }}

So that finally I can do this kind of thing:

所以最后我可以做这样的事情:

private string _name;public string Name{    get { return _name; }    set { this.NotifySetProperty(ref _name, value, () => this.Name); }}

It's strongly-typed and I only raise events for properties that actually change their value.

它是强类型的,我只为实际改变其值的属性引发事件。

#4


Well this isn't exactly clever but I've modified the ----OrDefault methods so you could specify a default item inline instead of checking for null later in your code:

嗯,这不是很聪明,但我修改了---- OrDefault方法,因此您可以指定一个默认的内联项,而不是在代码中稍后检查null:

    public static T SingleOrDefault<T> ( this IEnumerable<T> source,                                     Func<T, bool> action, T theDefault )    {        T item = source.SingleOrDefault<T>(action);        if (item != null)            return item;        return theDefault;    }

Its incredible simple but really helps clean up those null checks. Best used when your UI is expecting a list of X items, like a tournament system, or game player slots and you want to display "empty seats".

它令人难以置信的简单,但真的有助于清理那些空检查。当您的UI期望X项目列表(如锦标赛系统或游戏玩家插槽)并且您希望显示“空座位”时,最佳使用。

Usage:

    return jediList.SingleOrDefault(                  j => j.LightsaberColor == "Orange",                new Jedi() { LightsaberColor = "Orange", Name = "DarthNobody");

#5


Here's one I hacked together, so feel free to pick holes in it. It takes an (ordered) list of integers and returns a list of strings of contiguous ranges. eg:

这是我一起砍的一个,所以随意挑选它。它采用(有序)整数列表并返回连续范围的字符串列表。例如:

1,2,3,7,10,11,12  -->  "1-3","7","10-12"

The function (within a static class):

该函数(在静态类中):

public static IEnumerable<string> IntRanges(this IEnumerable<int> numbers){    int rangeStart = 0;    int previous = 0;    if (!numbers.Any())        yield break;    rangeStart = previous = numbers.FirstOrDefault();    foreach (int n in numbers.Skip(1))    {        if (n - previous > 1) // sequence break - yield a sequence        {            if (previous > rangeStart)            {                yield return string.Format("{0}-{1}", rangeStart, previous);            }            else            {                yield return rangeStart.ToString();            }            rangeStart = n;        }        previous = n;    }    if (previous > rangeStart)    {        yield return string.Format("{0}-{1}", rangeStart, previous);    }    else    {        yield return rangeStart.ToString();    }}

Usage example:

this.WeekDescription = string.Join(",", from.WeekPattern.WeekPatternToInts().IntRanges().ToArray());

This code is used to convert data from a DailyWTF-worthy timetabling application. WeekPattern is a bitmask stored in a string "0011011100...". WeekPatternToInts() converts that to an IEnumerable<int>, in this case [3,4,6,7,8], which becomes "3-4,6-8". It provides the user with a compact description of the academic week ranges that a lecture occurs on.

此代码用于转换DailyWTF值得的时间表应用程序中的数据。 WeekPattern是存储在字符串“0011011100 ...”中的位掩码。 WeekPatternToInts()将其转换为IEnumerable ,在本例中为[3,4,6,7,8],变为“3-4,6-8”。它为用户提供了讲座发生的学术周范围的简洁描述。

#6


Two that I like to use are the InsertWhere<T> and RemoveWhere<T> Extension Methods that I've written. Working with ObservableCollections in WPF and Silverlight I often need to modify ordered lists without recreating them. These methods allow me to insert and remove according to a supplied Func, so .OrderBy() doesn't need to be re-called.

我喜欢使用的两个是我编写的InsertWhere 和RemoveWhere 扩展方法。在WPF和Silverlight中使用ObservableCollections我经常需要修改有序列表而不重新创建它们。这些方法允许我根据提供的Func插入和删除,因此.OrderBy()不需要重新调用。

    /// <summary>    /// Removes all items from the provided <paramref name="list"/> that match the<paramref name="predicate"/> expression.    /// </summary>    /// <typeparam name="T">The class type of the list items.</typeparam>    /// <param name="list">The list to remove items from.</param>    /// <param name="predicate">The predicate expression to test against.</param>    public static void RemoveWhere<T>(this IList<T> list, Func<T, bool> predicate)    {        T[] copy = new T[] { };        Array.Resize(ref copy, list.Count);        list.CopyTo(copy, 0);        for (int i = copy.Length - 1; i >= 0; i--)        {            if (predicate(copy[i]))            {                list.RemoveAt(i);            }        }    }    /// <summary>    /// Inserts an Item into a list at the first place that the <paramref name="predicate"/> expression fails.  If it is true in all cases, then the item is appended to the end of the list.    /// </summary>    /// <typeparam name="T"></typeparam>    /// <param name="list"></param>    /// <param name="obj"></param>    /// <param name="predicate">The sepcified function that determines when the <paramref name="obj"/> should be added. </param>    public static void InsertWhere<T>(this IList<T> list, T obj, Func<T, bool> predicate)    {        for (int i = 0; i < list.Count; i++)        {             // When the function first fails it inserts the obj paramiter.             // For example, in a list myList of ordered Int32's {1,2,3,4,5,10,12}            // Calling myList.InsertWhere( 8, x => 8 > x) inserts 8 once the list item becomes greater then or equal to it.            if(!predicate(list[i]))            {                list.Insert(i, obj);                return;            }        }        list.Add(obj);    }

Edit:
Talljoe made some significant improvements to the RemoveWhere/RemoveAll, that I had hastily constructed. With ~3mill items removing every third one the new version takes only ~50 milliseconds (less then 10 if it can call List.RemoveAll !) as opposed to the RemoveWhere 's multiple seconds (I got tired of waiting for it.)

编辑:Talljoe对RemoveWhere / RemoveAll进行了一些重大改进,我已经匆忙构建了。每三个项目删除大约3个项目,新版本只需要约50毫秒(如果它可以调用List.RemoveAll,则少于10个!)而不是RemoveWhere的多秒(我厌倦了等待它。)

Here is his greatly improved version, thanks again!

这是他大大改进的版本,再次感谢!

    public static void RemoveAll<T>(this IList<T> instance, Predicate<T> predicate)    {        if (instance == null)            throw new ArgumentNullException("instance");        if (predicate == null)            throw new ArgumentNullException("predicate");        if (instance is T[])            throw new NotSupportedException();        var list = instance as List<T>;        if (list != null)        {            list.RemoveAll(predicate);            return;        }        int writeIndex = 0;        for (int readIndex = 0; readIndex < instance.Count; readIndex++)        {            var item = instance[readIndex];            if (predicate(item)) continue;            if (readIndex != writeIndex)            {                instance[writeIndex] = item;            }            ++writeIndex;        }        if (writeIndex != instance.Count)        {            for (int deleteIndex = instance.Count - 1; deleteIndex >= writeIndex; --deleteIndex)            {                instance.RemoveAt(deleteIndex);            }        }    }

#7


I have various .Debugify extension methods that are useful for dumping objects to a log file. For example, here's my Dictionary debugify (I have these for List, Datatable, param array, etc.):

我有各种.Debugify扩展方法,可用于将对象转储到日志文件。例如,这是我的字典调试(我有这些用于List,Datatable,param数组等):

public static string Debugify<TKey, TValue>(this Dictionary<TKey, TValue> dictionary) {    string Result = "";    if (dictionary.Count > 0) {        StringBuilder ResultBuilder = new StringBuilder();        int Counter = 0;        foreach (KeyValuePair<TKey, TValue> Entry in dictionary) {            Counter++;            ResultBuilder.AppendFormat("{0}: {1}, ", Entry.Key, Entry.Value);            if (Counter % 10 == 0) ResultBuilder.AppendLine();        }        Result = ResultBuilder.ToString();    }    return Result;}

And here's one for a DbParameterCollection (useful for dumping database calls to the log file):

这里有一个DbParameterCollection(用于将数据库调用转储到日志文件):

public static string Debugify(this DbParameterCollection parameters) {    List<string> ParameterValuesList = new List<string>();    foreach (DbParameter Parameter in parameters) {        string ParameterName, ParameterValue;        ParameterName = Parameter.ParameterName;        if (Parameter.Direction == ParameterDirection.ReturnValue)            continue;        if (Parameter.Value == null || Parameter.Value.Equals(DBNull.Value))            ParameterValue = "NULL";        else        {            switch (Parameter.DbType)            {                case DbType.String:                case DbType.Date:                case DbType.DateTime:                case DbType.Guid:                case DbType.Xml:                    ParameterValue                        = "'" + Parameter                                .Value                                .ToString()                                .Replace(Environment.NewLine, "")                                .Left(80, "...") + "'"; // Left... is another nice one                    break;                default:                    ParameterValue = Parameter.Value.ToString();                    break;            }            if (Parameter.Direction != ParameterDirection.Input)                ParameterValue += " " + Parameter.Direction.ToString();        }        ParameterValuesList.Add(string.Format("{0}={1}", ParameterName, ParameterValue));    }    return string.Join(", ", ParameterValuesList.ToArray());}

Example result:

Log.DebugFormat("EXEC {0} {1}", procName, params.Debugify);// EXEC spProcedure @intID=5, @nvName='Michael Haren', @intRefID=11 OUTPUT

Note that if you call this after your DB calls, you'll get the output parameters filled in, too. I call this on a line that includes the SP name so I can copy/paste the call into SSMS for debugging.

请注意,如果在数据库调用后调用此方法,您也将获得输出参数。我在一个包含SP名称的行上调用它,这样我就可以将调用复制/粘贴到SSMS中进行调试。


These make my log files pretty and easy to generate without interrupting my code.

这些使我的日志文件非常容易生成而不会中断我的代码。

#8


A pair of extension methods to convert base-36 strings(!) to integers:

一对扩展方法,用于将base-36字符串(!)转换为整数:

public static int ToBase10(this string base36){    if (string.IsNullOrEmpty(base36))        return 0;    int value = 0;    foreach (var c in base36.Trim())    {        value = value * 36 + c.ToBase10();    }    return value;}public static int ToBase10(this char c){    if (c >= '0' && c <= '9')        return c - '0';    c = char.ToUpper(c);    if (c >= 'A' && c <= 'Z')        return c - 'A' + 10;    return 0;}

(Some genius decided that the best way to store numbers in the database was to encode them to strings. Decimals take too much space. Hex is better, but doesnt use the characters G-Z. So obviously you extend base-16 to base-36!)

(有些天才决定在数据库中存储数字的最佳方法是将它们编码为字符串。小数点占用太多空间。十六进制更好,但不使用字符GZ。所以显然你将base-16扩展到base-36! )

#9


I wrote a series of extension methods to make it easier to manipulate ADO.NET objects and methods :

我编写了一系列扩展方法,以便更容易地操作ADO.NET对象和方法:

Create a DbCommand from a DbConnection in one instruction :

在一条指令中从DbConnection创建DbCommand:

    public static DbCommand CreateCommand(this DbConnection connection, string commandText)    {        DbCommand command = connection.CreateCommand();        command.CommandText = commandText;        return command;    }

Add a parameter to a DbCommand :

将参数添加到DbCommand:

    public static DbParameter AddParameter(this DbCommand command, string name, DbType dbType)    {        DbParameter p = AddParameter(command, name, dbType, 0, ParameterDirection.Input);        return p;    }    public static DbParameter AddParameter(this DbCommand command, string name, DbType dbType, object value)    {        DbParameter p = AddParameter(command, name, dbType, 0, ParameterDirection.Input);        p.Value = value;        return p;    }    public static DbParameter AddParameter(this DbCommand command, string name, DbType dbType, int size)    {        return AddParameter(command, name, dbType, size, ParameterDirection.Input);    }    public static DbParameter AddParameter(this DbCommand command, string name, DbType dbType, int size, ParameterDirection direction)    {        DbParameter parameter = command.CreateParameter();        parameter.ParameterName = name;        parameter.DbType = dbType;        parameter.Direction = direction;        parameter.Size = size;        command.Parameters.Add(parameter);        return parameter;    }

Access DbDataReader fields by name rather than index :

按名称而不是索引访问DbDataReader字段:

    public static DateTime GetDateTime(this DbDataReader reader, string name)    {        int i = reader.GetOrdinal(name);        return reader.GetDateTime(i);    }    public static decimal GetDecimal(this DbDataReader reader, string name)    {        int i = reader.GetOrdinal(name);        return reader.GetDecimal(i);    }    public static double GetDouble(this DbDataReader reader, string name)    {        int i = reader.GetOrdinal(name);        return reader.GetDouble(i);    }    public static string GetString(this DbDataReader reader, string name)    {        int i = reader.GetOrdinal(name);        return reader.GetString(i);    }    ...

Another (unrelated) extension method allows me to perform the DragMove operation (like in WPF) on WinForms forms and controls, see here.

另一个(不相关的)扩展方法允许我在WinForms表单和控件上执行DragMove操作(如在WPF中),请参见此处。

#10


Most examples for extension methods that I see here go against best practises.Extension methods are powerful, but should be used sparingly. In my experience, a static helper/utility class with old-school syntax would generally be preferrable for most of these.

我在这里看到的扩展方法的大多数示例都违背了最佳实践。扩展方法很强大,但应该谨慎使用。根据我的经验,具有旧式语法的静态助手/实用程序类通常对于大多数这些是优选的。

There is something to say for extension methods for Enums, as it's not possible for them to have methods. If you define them in the same namespace as your Enum and in the same assembly, they work transparently.

对于Enums的扩展方法,有一些话要说,因为它们不可能有方法。如果您在与Enum相同的命名空间中定义它们并在同一个程序集中,它们将以透明方式工作。

#11


While very simple, I find this one to be particularly useful since I get a page out of a full result set ten billion times a project:

虽然非常简单,但我发现这个特别有用,因为我从一个完整的结果集中获得了一个项目的100亿次页面:

public static class QueryableExtensions{    public static IQueryable<T> Page(this IQueryable<T> query, int pageNumber, int pageSize)    {        int skipCount = (pageNumber-1) * pageSize;        query = query.Skip(skipCount);        query = query.Take(pageSize);        return query;    }}

#12


Often times, I've needed to display a user-friendly value based on an Enum value, but didn't want to go the custom Attribute route, as it didn't seem too elegant.

通常,我需要根据Enum值显示用户友好的值,但不想使用自定义属性路由,因为它看起来不太优雅。

With this handy extension method:

有了这个方便的扩展方法:

public static string EnumValue(this MyEnum e) {    switch (e) {        case MyEnum.First:            return "First Friendly Value";        case MyEnum.Second:            return "Second Friendly Value";        case MyEnum.Third:            return "Third Friendly Value";    }    return "Horrible Failure!!";}

I can do this:

我可以做这个:

Console.WriteLine(MyEnum.First.EnumValue());

Yay!

#13


This is an extension method to centralize null checks before raising events.

这是一种在引发事件之前集中空检查的扩展方法。

public static class EventExtension{    public static void RaiseEvent<T>(this EventHandler<T> handler, object obj, T args) where T : EventArgs    {        EventHandler<T> theHandler = handler;        if (theHandler != null)        {            theHandler(obj, args);        }    }}

#14


This one is incredibly simple, but it's a check I do a lot so I ended up making an extension method for it. My favorite extension methods tend to be the really simple, straightforward ones like this, or like Taylor L's extension method for raising events.

这个非常简单,但是我做了很多检查,所以我最终为它做了一个扩展方法。我最喜欢的扩展方法往往是像这样简单,直接的扩展方法,或者像Taylor L'提升事件的扩展方法。

public static bool IsNullOrEmpty(this ICollection e){    return e == null || e.Count == 0;}

#15


To allow more functional combinator code:

要允许更多功能组合码:

    public static Func<T, R> TryCoalesce<T, R>(this Func<T, R> f, R coalesce)    {        return x =>            {                try                {                    return f(x);                }                catch                {                    return coalesce;                }            };    }    public static TResult TryCoalesce<T, TResult>(this Func<T, TResult> f, T p, TResult coalesce)    {        return f.TryCoalesce(coalesce)(p);    }

Then I could write something like this:

然后我可以这样写:

    public static int ParseInt(this string str, int coalesce)    {        return TryCoalesce(int.Parse, str, coalesce);    }

#16


Another set I use quite often is for coalescing IDictionary methods:

我经常使用的另一个集合是用于合并IDictionary方法:

    public static TValue Get<TKey, TValue>(this IDictionary<TKey, TValue> d, TKey key, Func<TValue> valueThunk)    {        TValue v = d.Get(key);        if (v == null)        {            v = valueThunk();            d.Add(key, v);        }        return v;    }    public static TValue Get<TKey, TValue>(this IDictionary<TKey, TValue> d, TKey key, TValue coalesce)    {        return Get(d, key, () => coalesce);    }

And for working with collections in general:

并且通常用于处理集合:

    public static IEnumerable<T> AsCollection<T>(this T item)    {        yield return item;    }

Then for tree-like structures:

那么对于树状结构:

    public static LinkedList<T> Up<T>(this T node, Func<T, T> parent)    {        var list = new LinkedList<T>();        node.Up(parent, n => list.AddFirst(n));        return list;    }

So I can then easily traverse and operate upon a up a class like:

因此,我可以轻松地遍历和操作类似的类:

class Category{    public string Name { get; set; }    public Category Parent { get; set; }}

Next, to facilitate function composition and a more F# like way of programming in C#:

接下来,为了便于在C#中使用函数组合和更多类似F#的编程方式:

public static Func<T, T> Func<T>(this Func<T, T> f){    return f;}public static Func<T1, R> Compose<T1, T2, R>(this Func<T1, T2> f, Func<T2, R> g){    return x => g(f(x));}

#17


I am converting a lot of Java to C#. Many of the methods vary only in capitalization or other small syntax differences. So Java code such as

我正在将大量的Java转换为C#。许多方法仅在大小写或其他小的语法差异方面有所不同。所以Java代码如

myString.toLowerCase();

will not compile but by adding an extension method

不会编译,但通过添加扩展方法

public static void toLowerCase(this string s){    s.ToLower();}

I can catch all the methods (and I assume a good compiler will inline this anyway?).

我可以捕获所有的方法(我假设一个好的编译器会内联这个吗?)。

It's certainly made the job much easier and more reliable.(I thank @Yuriy - see answer in: differences between StringBuilder in Java and C#) for the suggestion.

这肯定使得工作变得更容易和更可靠。(我感谢@Yuriy - 请参阅答案:Java中的StringBuilder和C#之间的差异)。

#18


I like this one. It is a variation on the String.Split method that allows the use of an escape character to suppress splitting when the split character is intended to be in the actual string.

我喜欢这一个。它是String.Split方法的一种变体,它允许使用转义字符来抑制当拆分字符位于实际字符串中时的拆分。

#19


Extension method on int to decode a bitmask specifying days (with first day of week being Monday in this case) to an enumeration of DayOfWeek enums:

int上的扩展方法,用于解码指定天数(在本例中为星期一是星期一)的位掩码到DayOfWeek枚举的枚举:

public static IEnumerable<DayOfWeek> Days(this int dayMask){    if ((dayMask & 1) > 0) yield return DayOfWeek.Monday;    if ((dayMask & 2) > 0) yield return DayOfWeek.Tuesday;    if ((dayMask & 4) > 0) yield return DayOfWeek.Wednesday;    if ((dayMask & 8) > 0) yield return DayOfWeek.Thursday;    if ((dayMask & 16) > 0) yield return DayOfWeek.Friday;    if ((dayMask & 32) > 0) yield return DayOfWeek.Saturday;    if ((dayMask & 64) > 0) yield return DayOfWeek.Sunday;}

#20


This one creates array with single element added at the very beginning:

这个创建了一开始就添加了单个元素的数组:

public static T[] Prepend<T>(this T[] array, T item){    T[] result = new T[array.Length + 1];    result[0] = item;    Array.Copy(array, 0, result, 1, array.Length);    return result;}string[] some = new string[] { "foo", "bar" };...some = some.Prepend("baz"); 

And this one helps me when I need to convert some expression to it's square:

当我需要将一些表达式转换为正方形时,这个可以帮助我:

public static double Sq(this double arg){    return arg * arg;}(x - x0).Sq() + (y - y0).Sq() + (z - z0).Sq()

#21


Here's another one I wrote:

这是我写的另一个:

    public static class StringExtensions    {        /// <summary>        /// Returns a Subset string starting at the specified start index and ending and the specified end        /// index.        /// </summary>        /// <param name="s">The string to retrieve the subset from.</param>        /// <param name="startIndex">The specified start index for the subset.</param>        /// <param name="endIndex">The specified end index for the subset.</param>        /// <returns>A Subset string starting at the specified start index and ending and the specified end        /// index.</returns>        public static string Subsetstring(this string s, int startIndex, int endIndex)        {            if (startIndex < 0) throw new ArgumentOutOfRangeException("startIndex", "Must be positive.");            if (endIndex < 0) throw new ArgumentOutOfRangeException("endIndex", "Must be positive.");            if (startIndex > endIndex) throw new ArgumentOutOfRangeException("endIndex", "Must be >= startIndex.");            return s.Substring(startIndex, (endIndex - startIndex));        }        /// <summary>        /// Finds the specified Start Text and the End Text in this string instance, and returns a string        /// containing all the text starting from startText, to the begining of endText. (endText is not        /// included.)        /// </summary>        /// <param name="s">The string to retrieve the subset from.</param>        /// <param name="startText">The Start Text to begin the Subset from.</param>        /// <param name="endText">The End Text to where the Subset goes to.</param>        /// <param name="ignoreCase">Whether or not to ignore case when comparing startText/endText to the string.</param>        /// <returns>A string containing all the text starting from startText, to the begining of endText.</returns>        public static string Subsetstring(this string s, string startText, string endText, bool ignoreCase)        {            if (string.IsNullOrEmpty(startText)) throw new ArgumentNullException("startText", "Must be filled.");            if (string.IsNullOrEmpty(endText)) throw new ArgumentNullException("endText", "Must be filled.");            string temp = s;            if (ignoreCase)            {                temp = s.ToUpperInvariant();                startText = startText.ToUpperInvariant();                endText = endText.ToUpperInvariant();            }            int start = temp.IndexOf(startText);            int end = temp.IndexOf(endText, start);            return Subsetstring(s, start, end);        }    }

The motivation behind this one was simple. It always bugged me how the built in Substring method took startindex and length as it's parameters. It's ALWAYS much more helpful to do startindex and endindex. So, I rolled my own:

这个背后的动机很简单。它始终告诉我内置的Substring方法如何将startindex和length作为参数。使用startindex和endindex总是更有帮助。所以,我自己动手:

Usage:

        string s = "This is a tester for my cool extension method!!";        s = s.Subsetstring("tester", "cool",true);

The reason I had to use Subsetstring was because Substring's overload already takes two ints. If anyone has a better name, please, let me know!!

我必须使用Subsetstring的原因是因为Substring的重载已经需要两个整数。如果有人有更好的名字,请告诉我!

#22


cool, also loving Extensions!

很酷,也很喜欢扩展!

here's a few.

这里有几个。

This one will get the last Date of a Month:

这个将获得一个月的最后一个日期:

<System.Runtime.CompilerServices.Extension()> _    Public Function GetLastMonthDay(ByVal Source As DateTime) As DateTime        Dim CurrentMonth As Integer = Source.Month        Dim MonthCounter As Integer = Source.Month        Dim LastDay As DateTime        Dim DateCounter As DateTime = Source        LastDay = Source        Do While MonthCounter = CurrentMonth            DateCounter = DateCounter.AddDays(1)            MonthCounter = DateCounter.Month            If MonthCounter = CurrentMonth Then                LastDay = DateCounter            End If        Loop        Return LastDay    End Function

these two make reflection a bit easier:

这两个使反射更容易:

 <System.Runtime.CompilerServices.Extension()> _    Public Function GetPropertyValue(Of ValueType)(ByVal Source As Object, ByVal PropertyName As String) As ValueType        Dim pInfo As System.Reflection.PropertyInfo        pInfo = Source.GetType.GetProperty(PropertyName)        If pInfo Is Nothing Then            Throw New Exception("Property " & PropertyName & " does not exists for object of type " & Source.GetType.Name)        Else            Return pInfo.GetValue(Source, Nothing)        End If    End Function    <System.Runtime.CompilerServices.Extension()> _    Public Function GetPropertyType(ByVal Source As Object, ByVal PropertyName As String) As Type        Dim pInfo As System.Reflection.PropertyInfo        pInfo = Source.GetType.GetProperty(PropertyName)        If pInfo Is Nothing Then            Throw New Exception("Property " & PropertyName & " does not exists for object of type " & Source.GetType.Name)        Else            Return pInfo.PropertyType        End If    End Function

#23


The extension methods I use the most would have to be the ones in the System.Linq.Enumerable class.

我最常使用的扩展方法必须是System.Linq.Enumerable类中的扩展方法。

And a good and useful extension to that list you can find in MoreLinq.

您可以在MoreLinq中找到该列表的一个很好且有用的扩展。

#24


There are a couple that I've mentioned here that I use:

我在这里提到了一些我使用的:

  • Easier checking on flags enums

    更容易检查标志枚举

    if( enumVar.IsSet( MyEnum.PossibleFlag ) ) //..then

    if(enumVar.IsSet(MyEnum.PossibleFlag))//..then

  • Inline checking of nulls

    内联检查空值

    myObject.IfNotNull( x => x.Property );

    myObject.IfNotNull(x => x.Property);

#25


few extensions I use mostly. first set is object extensions, really only for converting.

我主要使用的扩展很少。第一组是对象扩展,实际上只用于转换。

public static class ObjectExtension{    public static T As<T>(this object value)    {        return (value != null && value is T) ? (T)value : default(T);    }    public static int AsInt(this string value)    {        if (value.HasValue())        {            int result;            var success = int.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out result);            if (success)            {                return result;            }        }        return 0;    }    public static Guid AsGuid(this string value)    {        return value.HasValue() ? new Guid(value) : Guid.Empty;    }}

string extensions

public static class StringExtension{    public static bool HasValue(this string value)    {        return string.IsNullOrEmpty(value) == false;    }    public static string Slug(this string value)    {        if (value.HasValue())        {            var builder = new StringBuilder();            var slug = value.Trim().ToLower();            foreach (var c in slug)            {                switch (c)                {                    case ' ':                        builder.Append("-");                        break;                    case '&':                        builder.Append("and");                        break;                    default:                        if ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') && c != '-')                        {                            builder.Append(c);                        }                        break;                }            }            return builder.ToString();        }        return string.Empty;    }    public static string Truncate(this string value, int limit)    {        return (value.Length > limit) ? string.Concat(value.Substring(0, Math.Min(value.Length, limit)), "...") : value;    }}

and last is some enum extensions

最后是一些枚举扩展

public static class EnumExtensions{    public static bool Has<T>(this Enum source, params T[] values)    {        var value = Convert.ToInt32(source, CultureInfo.InvariantCulture);        foreach (var i in values)        {            var mask = Convert.ToInt32(i, CultureInfo.InvariantCulture);            if ((value & mask) == 0)            {                return false;            }        }        return true;    }    public static bool Has<T>(this Enum source, T values)    {        var value = Convert.ToInt32(source, CultureInfo.InvariantCulture);        var mask = Convert.ToInt32(values, CultureInfo.InvariantCulture);        return (value & mask) != 0;    }    public static T Add<T>(this Enum source, T v)    {        var value = Convert.ToInt32(source, CultureInfo.InvariantCulture);        var mask = Convert.ToInt32(v, CultureInfo.InvariantCulture);        return Enum.ToObject(typeof(T), value | mask).As<T>();    }    public static T Remove<T>(this Enum source, T v)    {        var value = Convert.ToInt32(source, CultureInfo.InvariantCulture);        var mask = Convert.ToInt32(v, CultureInfo.InvariantCulture);        return Enum.ToObject(typeof(T), value & ~mask).As<T>();    }    public static T AsEnum<T>(this string value)    {        try        {            return Enum.Parse(typeof(T), value, true).As<T>();        }        catch        {            return default(T);        }    }}

#26


With regular use of StringBuilder, you may see the need to combine AppendFormat() and AppendLine().

经常使用StringBuilder,您可能会发现需要组合AppendFormat()和AppendLine()。

public static void AppendFormatLine(this StringBuilder sb, string format, params object[] args){    sb.AppendFormat(format, args);    sb.AppendLine();}

Also, since I'm converting an application from VB6 to C#, the following are very useful to me:

此外,由于我正在将应用程序从VB6转换为C#,以下内容对我非常有用:

public static string Left(this string s, int length){    if (s.Length >= length)        return s.Substring(0, length);    throw new ArgumentException("Length must be less than the length of the string.");}public static string Right(this string s, int length){    if (s.Length >= length)        return s.Substring(s.Length - length, length);    throw new ArgumentException("Length must be less than the length of the string.");}

#27


My favourite from my own personal collection of string utils is one that will parse a strongly typed value from a string for any type that has a TryParse method:

我最喜欢的是我自己的字符串utils集合,它可以解析任何具有TryParse方法的类型的字符串中的强类型值:

public static class StringUtils{    /// <summary>    /// This method will parse a value from a string.    /// If the string is null or not the right format to parse a valid value,    /// it will return the default value provided.    /// </summary>    public static T To<t>(this string value, T defaultValue)        where T: struct    {        var type = typeof(T);        if (value != null)        {            var parse = type.GetMethod("TryParse", new Type[] { typeof(string), type.MakeByRefType() });            var parameters = new object[] { value, default(T) };            if((bool)parse.Invoke(null, parameters))                return (T)parameters[1];        }        return defaultValue;    }    /// <summary>    /// This method will parse a value from a string.    /// If the string is null or not the right format to parse a valid value,    /// it will return the default value for the type.    /// </summary>    public static T To<t>(this string value)        where T : struct    {        return value.To<t>(default(T));    }}

It's great for getting strongly typed information from query strings:

它非常适合从查询字符串中获取强类型信息:

var value = Request.QueryString["value"].To<int>();

#28


I hate having to do this everywhere:

我不想到处都这样做:

DataSet ds = dataLayer.GetSomeData(1, 2, 3);if(ds != null){    if(ds.Tables.Count > 0){        DataTable dt = ds.Tables[0];        foreach(DataRow dr in dt.Rows){            //Do some processing        }    }}

Instead I usually use the following Extension Method:

相反,我通常使用以下扩展方法:

public static IEnumerable<DataRow> DataRows(this DataSet current){    if(current != null){        if(current.Tables.Count > 0){            DataTable dt = current.Tables[0];            foreach(DataRow dr in dt.Rows){                yield return dr;            }        }    }}

So the first example then becomes:

那么第一个例子就变成了:

foreach(DataRow row in ds.DataRows()){    //Do some processing}

Yay, Extension Methods!

耶,扩展方法!

#29


String.format should not have been static. So I use an extension method called frmt:

String.format不应该是静态的。所以我使用一个名为frmt的扩展方法:

<Extension()> Public Function frmt(ByVal format As String,                                   ByVal ParamArray args() As Object) As String    If format Is Nothing Then Throw New ArgumentNullException("format")    Return String.Format(format, args)End Function

When I want to read or write a number to a byte stream without constructing a binary writer (technically you aren't supposed to modify the raw stream after you've wrapped it with a writer):

当我想在没有构建二进制编写器的情况下读取或写入字节流的数字时(从技术上讲,在用编写器包装后不应该修改原始流):

<Extension()> Public Function Bytes(ByVal n As ULong,                                    ByVal byteOrder As ByteOrder,                                    Optional ByVal size As Integer = 8) As Byte()    Dim data As New List(Of Byte)    Do Until data.Count >= size        data.Add(CByte(n And CULng(&HFF)))        n >>= 8    Loop    Select Case byteOrder        Case ByteOrder.BigEndian            Return data.ToArray.reversed        Case ByteOrder.LittleEndian            Return data.ToArray        Case Else            Throw New ArgumentException("Unrecognized byte order.")    End SelectEnd Function<Extension()> Public Function ToULong(ByVal data As IEnumerable(Of Byte),                                      ByVal byteOrder As ByteOrder) As ULong    If data Is Nothing Then Throw New ArgumentNullException("data")    Dim val As ULong    Select Case byteOrder        Case ByteOrder.LittleEndian            data = data.Reverse        Case ByteOrder.BigEndian            'no change required        Case Else            Throw New ArgumentException("Unrecognized byte order.")    End Select    For Each b In data        val <<= 8        val = val Or b    Next b    Return valEnd Function

#30


This one shifts a sequence so that you get the given item first. I used it for example to take the day of weeks and shift it so that the first day in the sequence is the first day of the week for the current culture.

这个移动一个序列,以便您首先获得给定的项目。例如,我用它来取几周的时间并将其移动,以便序列中的第一天是当前文化的一周的第一天。

    /// <summary>    /// Shifts a sequence so that the given <paramref name="item"/> becomes the first.     /// Uses the specified equality <paramref name="comparer"/> to find the item.    /// </summary>    /// <typeparam name="TSource">Type of elements in <paramref name="source"/>.</typeparam>    /// <param name="source">Sequence of elements.</param>    /// <param name="item">Item which will become the first.</param>    /// <param name="comparer">Used to find the first item.</param>    /// <returns>A shifted sequence. For example Shift({1,2,3,4,5,6}, 3) would become {3,4,5,6,1,2}. </returns>    public static IEnumerable<TSource> Shift<TSource>(this IEnumerable<TSource> source, TSource item, IEqualityComparer<TSource> comparer)    {        var queue = new Queue<TSource>();        bool found = false;        foreach (TSource e in source)        {            if (!found && comparer.Equals(item, e))                found = true;            if (found)                yield return e;            else                queue.Enqueue(e);        }        while (queue.Count > 0)            yield return queue.Dequeue();    }    /// <summary>    /// Shifts a sequence so that the given item becomes the first.     /// Uses the default equality comparer to find the item.    /// </summary>    /// <typeparam name="TSource">Type of elements in <paramref name="source"/>.</typeparam>    /// <param name="source">Sequence of elements.</param>    /// <param name="element">Element which will become the first.</param>    /// <returns>A shifted sequence. For example Shift({1,2,3,4,5,6}, 3) would become {3,4,5,6,1,2}. </returns>    public static IEnumerable<TSource> Shift<TSource>(this IEnumerable<TSource> source, TSource element)    {        return Shift(source, element, EqualityComparer<TSource>.Default);    }

#1


The full solution is too large to put here, but I wrote a series of extension methods that would allow you to easily convert a DataTable into a CSV.

完整的解决方案太大了,不能放在这里,但我写了一系列扩展方法,可以让你轻松地将DataTable转换为CSV。

public static String ToCSV(this DataTable dataTable){    return dataTable.ToCSV(null, COMMA, true);}  public static String ToCSV(this DataTable dataTable, String qualifier){    return dataTable.ToCSV(qualifier, COMMA, true);}private static String ToCSV(this DataTable dataTable, String qualifier, String delimiter, Boolean includeColumnNames){    if (dataTable == null) return null;    if (qualifier == delimiter)    {        throw new InvalidOperationException(            "The qualifier and the delimiter are identical. This will cause the CSV to have collisions that might result in data being parsed incorrectly by another program.");    }    var sbCSV = new StringBuilder();    var delimiterToUse = delimiter ?? COMMA;    if (includeColumnNames)         sbCSV.AppendLine(dataTable.Columns.GetHeaderLine(qualifier, delimiterToUse));    foreach (DataRow row in dataTable.Rows)    {        sbCSV.AppendLine(row.ToCSVLine(qualifier, delimiterToUse));    }    return sbCSV.Length > 0 ? sbCSV.ToString() : null;}private static String ToCSVLine(this DataRow dataRow, String qualifier, String delimiter){    var colCount = dataRow.Table.Columns.Count;    var rowValues = new String[colCount];    for (var i = 0; i < colCount; i++)    {        rowValues[i] = dataRow[i].Qualify(qualifier);    }    return String.Join(delimiter, rowValues);}private static String GetHeaderLine(this DataColumnCollection columns, String qualifier, String delimiter){    var colCount = columns.Count;    var colNames = new String[colCount];    for (var i = 0; i < colCount; i++)    {        colNames[i] = columns[i].ColumnName.Qualify(qualifier);    }    return String.Join(delimiter, colNames);}private static String Qualify(this Object target, String qualifier){    return qualifier + target + qualifier;}

At the end of the day, you could call it like this:

在一天结束时,您可以这样称呼它:

someDataTable.ToCSV(); //Plain old CSVsomeDataTable.ToCSV("\""); //Double quote qualifiersomeDataTable.ToCSV("\"", "\t"); //Tab delimited

#2


This is one that's been getting some play from me lately:

这是最近一直在玩我的游戏:

public static IDisposable Tag(this HtmlHelper html, string tagName){    if (html == null)        throw new ArgumentNullException("html");    Action<string> a = tag => html.Write(String.Format(tag, tagName));    a("<{0}>");    return new Memento(() => a("</{0}>"));}

Used like:

using (Html.Tag("ul")){    this.Model.ForEach(item => using(Html.Tag("li")) Html.Write(item));    using(Html.Tag("li")) Html.Write("new");}

Memento is a handy class:

纪念品是一个方便的课程:

public sealed class Memento : IDisposable{    private bool Disposed { get; set; }    private Action Action { get; set; }    public Memento(Action action)    {        if (action == null)            throw new ArgumentNullException("action");        Action = action;    }    void IDisposable.Dispose()    {        if (Disposed)            throw new ObjectDisposedException("Memento");        Disposed = true;        Action();    }}

And to complete the dependencies:

并完成依赖:

public static void Write(this HtmlHelper html, string content){    if (html == null)        throw new ArgumentNullException("html");    html.ViewContext.HttpContext.Response.Write(content);}

#3


I'm not a fan of the INotifyPropertyChanged interface requiring that property names are passed as strings. I want a strongly-typed way to check at compile time that I'm only raising and handling property changes for properties that exist. I use this code to do that:

我不是INotifyPropertyChanged接口的粉丝,要求将属性名称作为字符串传递。我想要一种强类型的方法在编译时检查我只是为现有的属性提出并处理属性更改。我使用这段代码来做到这一点:

public static class INotifyPropertyChangedExtensions{    public static string ToPropertyName<T>(this Expression<Func<T>> @this)    {        var @return = string.Empty;        if (@this != null)        {            var memberExpression = @this.Body as MemberExpression;            if (memberExpression != null)            {                @return = memberExpression.Member.Name;            }        }        return @return;    }}

In classes that implement INotifyPropertyChanged I include this helper method:

在实现INotifyPropertyChanged的类中,我包含了这个帮助器方法:

protected void NotifySetProperty<T>(ref T field, T value,    Expression<Func<T>> propertyExpression){    if (field == null ? value != null : !field.Equals(value))    {        field = value;        this.NotifyPropertyChanged(propertyExpression.ToPropertyName());    }}

So that finally I can do this kind of thing:

所以最后我可以做这样的事情:

private string _name;public string Name{    get { return _name; }    set { this.NotifySetProperty(ref _name, value, () => this.Name); }}

It's strongly-typed and I only raise events for properties that actually change their value.

它是强类型的,我只为实际改变其值的属性引发事件。

#4


Well this isn't exactly clever but I've modified the ----OrDefault methods so you could specify a default item inline instead of checking for null later in your code:

嗯,这不是很聪明,但我修改了---- OrDefault方法,因此您可以指定一个默认的内联项,而不是在代码中稍后检查null:

    public static T SingleOrDefault<T> ( this IEnumerable<T> source,                                     Func<T, bool> action, T theDefault )    {        T item = source.SingleOrDefault<T>(action);        if (item != null)            return item;        return theDefault;    }

Its incredible simple but really helps clean up those null checks. Best used when your UI is expecting a list of X items, like a tournament system, or game player slots and you want to display "empty seats".

它令人难以置信的简单,但真的有助于清理那些空检查。当您的UI期望X项目列表(如锦标赛系统或游戏玩家插槽)并且您希望显示“空座位”时,最佳使用。

Usage:

    return jediList.SingleOrDefault(                  j => j.LightsaberColor == "Orange",                new Jedi() { LightsaberColor = "Orange", Name = "DarthNobody");

#5


Here's one I hacked together, so feel free to pick holes in it. It takes an (ordered) list of integers and returns a list of strings of contiguous ranges. eg:

这是我一起砍的一个,所以随意挑选它。它采用(有序)整数列表并返回连续范围的字符串列表。例如:

1,2,3,7,10,11,12  -->  "1-3","7","10-12"

The function (within a static class):

该函数(在静态类中):

public static IEnumerable<string> IntRanges(this IEnumerable<int> numbers){    int rangeStart = 0;    int previous = 0;    if (!numbers.Any())        yield break;    rangeStart = previous = numbers.FirstOrDefault();    foreach (int n in numbers.Skip(1))    {        if (n - previous > 1) // sequence break - yield a sequence        {            if (previous > rangeStart)            {                yield return string.Format("{0}-{1}", rangeStart, previous);            }            else            {                yield return rangeStart.ToString();            }            rangeStart = n;        }        previous = n;    }    if (previous > rangeStart)    {        yield return string.Format("{0}-{1}", rangeStart, previous);    }    else    {        yield return rangeStart.ToString();    }}

Usage example:

this.WeekDescription = string.Join(",", from.WeekPattern.WeekPatternToInts().IntRanges().ToArray());

This code is used to convert data from a DailyWTF-worthy timetabling application. WeekPattern is a bitmask stored in a string "0011011100...". WeekPatternToInts() converts that to an IEnumerable<int>, in this case [3,4,6,7,8], which becomes "3-4,6-8". It provides the user with a compact description of the academic week ranges that a lecture occurs on.

此代码用于转换DailyWTF值得的时间表应用程序中的数据。 WeekPattern是存储在字符串“0011011100 ...”中的位掩码。 WeekPatternToInts()将其转换为IEnumerable ,在本例中为[3,4,6,7,8],变为“3-4,6-8”。它为用户提供了讲座发生的学术周范围的简洁描述。

#6


Two that I like to use are the InsertWhere<T> and RemoveWhere<T> Extension Methods that I've written. Working with ObservableCollections in WPF and Silverlight I often need to modify ordered lists without recreating them. These methods allow me to insert and remove according to a supplied Func, so .OrderBy() doesn't need to be re-called.

我喜欢使用的两个是我编写的InsertWhere 和RemoveWhere 扩展方法。在WPF和Silverlight中使用ObservableCollections我经常需要修改有序列表而不重新创建它们。这些方法允许我根据提供的Func插入和删除,因此.OrderBy()不需要重新调用。

    /// <summary>    /// Removes all items from the provided <paramref name="list"/> that match the<paramref name="predicate"/> expression.    /// </summary>    /// <typeparam name="T">The class type of the list items.</typeparam>    /// <param name="list">The list to remove items from.</param>    /// <param name="predicate">The predicate expression to test against.</param>    public static void RemoveWhere<T>(this IList<T> list, Func<T, bool> predicate)    {        T[] copy = new T[] { };        Array.Resize(ref copy, list.Count);        list.CopyTo(copy, 0);        for (int i = copy.Length - 1; i >= 0; i--)        {            if (predicate(copy[i]))            {                list.RemoveAt(i);            }        }    }    /// <summary>    /// Inserts an Item into a list at the first place that the <paramref name="predicate"/> expression fails.  If it is true in all cases, then the item is appended to the end of the list.    /// </summary>    /// <typeparam name="T"></typeparam>    /// <param name="list"></param>    /// <param name="obj"></param>    /// <param name="predicate">The sepcified function that determines when the <paramref name="obj"/> should be added. </param>    public static void InsertWhere<T>(this IList<T> list, T obj, Func<T, bool> predicate)    {        for (int i = 0; i < list.Count; i++)        {             // When the function first fails it inserts the obj paramiter.             // For example, in a list myList of ordered Int32's {1,2,3,4,5,10,12}            // Calling myList.InsertWhere( 8, x => 8 > x) inserts 8 once the list item becomes greater then or equal to it.            if(!predicate(list[i]))            {                list.Insert(i, obj);                return;            }        }        list.Add(obj);    }

Edit:
Talljoe made some significant improvements to the RemoveWhere/RemoveAll, that I had hastily constructed. With ~3mill items removing every third one the new version takes only ~50 milliseconds (less then 10 if it can call List.RemoveAll !) as opposed to the RemoveWhere 's multiple seconds (I got tired of waiting for it.)

编辑:Talljoe对RemoveWhere / RemoveAll进行了一些重大改进,我已经匆忙构建了。每三个项目删除大约3个项目,新版本只需要约50毫秒(如果它可以调用List.RemoveAll,则少于10个!)而不是RemoveWhere的多秒(我厌倦了等待它。)

Here is his greatly improved version, thanks again!

这是他大大改进的版本,再次感谢!

    public static void RemoveAll<T>(this IList<T> instance, Predicate<T> predicate)    {        if (instance == null)            throw new ArgumentNullException("instance");        if (predicate == null)            throw new ArgumentNullException("predicate");        if (instance is T[])            throw new NotSupportedException();        var list = instance as List<T>;        if (list != null)        {            list.RemoveAll(predicate);            return;        }        int writeIndex = 0;        for (int readIndex = 0; readIndex < instance.Count; readIndex++)        {            var item = instance[readIndex];            if (predicate(item)) continue;            if (readIndex != writeIndex)            {                instance[writeIndex] = item;            }            ++writeIndex;        }        if (writeIndex != instance.Count)        {            for (int deleteIndex = instance.Count - 1; deleteIndex >= writeIndex; --deleteIndex)            {                instance.RemoveAt(deleteIndex);            }        }    }

#7


I have various .Debugify extension methods that are useful for dumping objects to a log file. For example, here's my Dictionary debugify (I have these for List, Datatable, param array, etc.):

我有各种.Debugify扩展方法,可用于将对象转储到日志文件。例如,这是我的字典调试(我有这些用于List,Datatable,param数组等):

public static string Debugify<TKey, TValue>(this Dictionary<TKey, TValue> dictionary) {    string Result = "";    if (dictionary.Count > 0) {        StringBuilder ResultBuilder = new StringBuilder();        int Counter = 0;        foreach (KeyValuePair<TKey, TValue> Entry in dictionary) {            Counter++;            ResultBuilder.AppendFormat("{0}: {1}, ", Entry.Key, Entry.Value);            if (Counter % 10 == 0) ResultBuilder.AppendLine();        }        Result = ResultBuilder.ToString();    }    return Result;}

And here's one for a DbParameterCollection (useful for dumping database calls to the log file):

这里有一个DbParameterCollection(用于将数据库调用转储到日志文件):

public static string Debugify(this DbParameterCollection parameters) {    List<string> ParameterValuesList = new List<string>();    foreach (DbParameter Parameter in parameters) {        string ParameterName, ParameterValue;        ParameterName = Parameter.ParameterName;        if (Parameter.Direction == ParameterDirection.ReturnValue)            continue;        if (Parameter.Value == null || Parameter.Value.Equals(DBNull.Value))            ParameterValue = "NULL";        else        {            switch (Parameter.DbType)            {                case DbType.String:                case DbType.Date:                case DbType.DateTime:                case DbType.Guid:                case DbType.Xml:                    ParameterValue                        = "'" + Parameter                                .Value                                .ToString()                                .Replace(Environment.NewLine, "")                                .Left(80, "...") + "'"; // Left... is another nice one                    break;                default:                    ParameterValue = Parameter.Value.ToString();                    break;            }            if (Parameter.Direction != ParameterDirection.Input)                ParameterValue += " " + Parameter.Direction.ToString();        }        ParameterValuesList.Add(string.Format("{0}={1}", ParameterName, ParameterValue));    }    return string.Join(", ", ParameterValuesList.ToArray());}

Example result:

Log.DebugFormat("EXEC {0} {1}", procName, params.Debugify);// EXEC spProcedure @intID=5, @nvName='Michael Haren', @intRefID=11 OUTPUT

Note that if you call this after your DB calls, you'll get the output parameters filled in, too. I call this on a line that includes the SP name so I can copy/paste the call into SSMS for debugging.

请注意,如果在数据库调用后调用此方法,您也将获得输出参数。我在一个包含SP名称的行上调用它,这样我就可以将调用复制/粘贴到SSMS中进行调试。


These make my log files pretty and easy to generate without interrupting my code.

这些使我的日志文件非常容易生成而不会中断我的代码。

#8


A pair of extension methods to convert base-36 strings(!) to integers:

一对扩展方法,用于将base-36字符串(!)转换为整数:

public static int ToBase10(this string base36){    if (string.IsNullOrEmpty(base36))        return 0;    int value = 0;    foreach (var c in base36.Trim())    {        value = value * 36 + c.ToBase10();    }    return value;}public static int ToBase10(this char c){    if (c >= '0' && c <= '9')        return c - '0';    c = char.ToUpper(c);    if (c >= 'A' && c <= 'Z')        return c - 'A' + 10;    return 0;}

(Some genius decided that the best way to store numbers in the database was to encode them to strings. Decimals take too much space. Hex is better, but doesnt use the characters G-Z. So obviously you extend base-16 to base-36!)

(有些天才决定在数据库中存储数字的最佳方法是将它们编码为字符串。小数点占用太多空间。十六进制更好,但不使用字符GZ。所以显然你将base-16扩展到base-36! )

#9


I wrote a series of extension methods to make it easier to manipulate ADO.NET objects and methods :

我编写了一系列扩展方法,以便更容易地操作ADO.NET对象和方法:

Create a DbCommand from a DbConnection in one instruction :

在一条指令中从DbConnection创建DbCommand:

    public static DbCommand CreateCommand(this DbConnection connection, string commandText)    {        DbCommand command = connection.CreateCommand();        command.CommandText = commandText;        return command;    }

Add a parameter to a DbCommand :

将参数添加到DbCommand:

    public static DbParameter AddParameter(this DbCommand command, string name, DbType dbType)    {        DbParameter p = AddParameter(command, name, dbType, 0, ParameterDirection.Input);        return p;    }    public static DbParameter AddParameter(this DbCommand command, string name, DbType dbType, object value)    {        DbParameter p = AddParameter(command, name, dbType, 0, ParameterDirection.Input);        p.Value = value;        return p;    }    public static DbParameter AddParameter(this DbCommand command, string name, DbType dbType, int size)    {        return AddParameter(command, name, dbType, size, ParameterDirection.Input);    }    public static DbParameter AddParameter(this DbCommand command, string name, DbType dbType, int size, ParameterDirection direction)    {        DbParameter parameter = command.CreateParameter();        parameter.ParameterName = name;        parameter.DbType = dbType;        parameter.Direction = direction;        parameter.Size = size;        command.Parameters.Add(parameter);        return parameter;    }

Access DbDataReader fields by name rather than index :

按名称而不是索引访问DbDataReader字段:

    public static DateTime GetDateTime(this DbDataReader reader, string name)    {        int i = reader.GetOrdinal(name);        return reader.GetDateTime(i);    }    public static decimal GetDecimal(this DbDataReader reader, string name)    {        int i = reader.GetOrdinal(name);        return reader.GetDecimal(i);    }    public static double GetDouble(this DbDataReader reader, string name)    {        int i = reader.GetOrdinal(name);        return reader.GetDouble(i);    }    public static string GetString(this DbDataReader reader, string name)    {        int i = reader.GetOrdinal(name);        return reader.GetString(i);    }    ...

Another (unrelated) extension method allows me to perform the DragMove operation (like in WPF) on WinForms forms and controls, see here.

另一个(不相关的)扩展方法允许我在WinForms表单和控件上执行DragMove操作(如在WPF中),请参见此处。

#10


Most examples for extension methods that I see here go against best practises.Extension methods are powerful, but should be used sparingly. In my experience, a static helper/utility class with old-school syntax would generally be preferrable for most of these.

我在这里看到的扩展方法的大多数示例都违背了最佳实践。扩展方法很强大,但应该谨慎使用。根据我的经验,具有旧式语法的静态助手/实用程序类通常对于大多数这些是优选的。

There is something to say for extension methods for Enums, as it's not possible for them to have methods. If you define them in the same namespace as your Enum and in the same assembly, they work transparently.

对于Enums的扩展方法,有一些话要说,因为它们不可能有方法。如果您在与Enum相同的命名空间中定义它们并在同一个程序集中,它们将以透明方式工作。

#11


While very simple, I find this one to be particularly useful since I get a page out of a full result set ten billion times a project:

虽然非常简单,但我发现这个特别有用,因为我从一个完整的结果集中获得了一个项目的100亿次页面:

public static class QueryableExtensions{    public static IQueryable<T> Page(this IQueryable<T> query, int pageNumber, int pageSize)    {        int skipCount = (pageNumber-1) * pageSize;        query = query.Skip(skipCount);        query = query.Take(pageSize);        return query;    }}

#12


Often times, I've needed to display a user-friendly value based on an Enum value, but didn't want to go the custom Attribute route, as it didn't seem too elegant.

通常,我需要根据Enum值显示用户友好的值,但不想使用自定义属性路由,因为它看起来不太优雅。

With this handy extension method:

有了这个方便的扩展方法:

public static string EnumValue(this MyEnum e) {    switch (e) {        case MyEnum.First:            return "First Friendly Value";        case MyEnum.Second:            return "Second Friendly Value";        case MyEnum.Third:            return "Third Friendly Value";    }    return "Horrible Failure!!";}

I can do this:

我可以做这个:

Console.WriteLine(MyEnum.First.EnumValue());

Yay!

#13


This is an extension method to centralize null checks before raising events.

这是一种在引发事件之前集中空检查的扩展方法。

public static class EventExtension{    public static void RaiseEvent<T>(this EventHandler<T> handler, object obj, T args) where T : EventArgs    {        EventHandler<T> theHandler = handler;        if (theHandler != null)        {            theHandler(obj, args);        }    }}

#14


This one is incredibly simple, but it's a check I do a lot so I ended up making an extension method for it. My favorite extension methods tend to be the really simple, straightforward ones like this, or like Taylor L's extension method for raising events.

这个非常简单,但是我做了很多检查,所以我最终为它做了一个扩展方法。我最喜欢的扩展方法往往是像这样简单,直接的扩展方法,或者像Taylor L'提升事件的扩展方法。

public static bool IsNullOrEmpty(this ICollection e){    return e == null || e.Count == 0;}

#15


To allow more functional combinator code:

要允许更多功能组合码:

    public static Func<T, R> TryCoalesce<T, R>(this Func<T, R> f, R coalesce)    {        return x =>            {                try                {                    return f(x);                }                catch                {                    return coalesce;                }            };    }    public static TResult TryCoalesce<T, TResult>(this Func<T, TResult> f, T p, TResult coalesce)    {        return f.TryCoalesce(coalesce)(p);    }

Then I could write something like this:

然后我可以这样写:

    public static int ParseInt(this string str, int coalesce)    {        return TryCoalesce(int.Parse, str, coalesce);    }

#16


Another set I use quite often is for coalescing IDictionary methods:

我经常使用的另一个集合是用于合并IDictionary方法:

    public static TValue Get<TKey, TValue>(this IDictionary<TKey, TValue> d, TKey key, Func<TValue> valueThunk)    {        TValue v = d.Get(key);        if (v == null)        {            v = valueThunk();            d.Add(key, v);        }        return v;    }    public static TValue Get<TKey, TValue>(this IDictionary<TKey, TValue> d, TKey key, TValue coalesce)    {        return Get(d, key, () => coalesce);    }

And for working with collections in general:

并且通常用于处理集合:

    public static IEnumerable<T> AsCollection<T>(this T item)    {        yield return item;    }

Then for tree-like structures:

那么对于树状结构:

    public static LinkedList<T> Up<T>(this T node, Func<T, T> parent)    {        var list = new LinkedList<T>();        node.Up(parent, n => list.AddFirst(n));        return list;    }

So I can then easily traverse and operate upon a up a class like:

因此,我可以轻松地遍历和操作类似的类:

class Category{    public string Name { get; set; }    public Category Parent { get; set; }}

Next, to facilitate function composition and a more F# like way of programming in C#:

接下来,为了便于在C#中使用函数组合和更多类似F#的编程方式:

public static Func<T, T> Func<T>(this Func<T, T> f){    return f;}public static Func<T1, R> Compose<T1, T2, R>(this Func<T1, T2> f, Func<T2, R> g){    return x => g(f(x));}

#17


I am converting a lot of Java to C#. Many of the methods vary only in capitalization or other small syntax differences. So Java code such as

我正在将大量的Java转换为C#。许多方法仅在大小写或其他小的语法差异方面有所不同。所以Java代码如

myString.toLowerCase();

will not compile but by adding an extension method

不会编译,但通过添加扩展方法

public static void toLowerCase(this string s){    s.ToLower();}

I can catch all the methods (and I assume a good compiler will inline this anyway?).

我可以捕获所有的方法(我假设一个好的编译器会内联这个吗?)。

It's certainly made the job much easier and more reliable.(I thank @Yuriy - see answer in: differences between StringBuilder in Java and C#) for the suggestion.

这肯定使得工作变得更容易和更可靠。(我感谢@Yuriy - 请参阅答案:Java中的StringBuilder和C#之间的差异)。

#18


I like this one. It is a variation on the String.Split method that allows the use of an escape character to suppress splitting when the split character is intended to be in the actual string.

我喜欢这一个。它是String.Split方法的一种变体,它允许使用转义字符来抑制当拆分字符位于实际字符串中时的拆分。

#19


Extension method on int to decode a bitmask specifying days (with first day of week being Monday in this case) to an enumeration of DayOfWeek enums:

int上的扩展方法,用于解码指定天数(在本例中为星期一是星期一)的位掩码到DayOfWeek枚举的枚举:

public static IEnumerable<DayOfWeek> Days(this int dayMask){    if ((dayMask & 1) > 0) yield return DayOfWeek.Monday;    if ((dayMask & 2) > 0) yield return DayOfWeek.Tuesday;    if ((dayMask & 4) > 0) yield return DayOfWeek.Wednesday;    if ((dayMask & 8) > 0) yield return DayOfWeek.Thursday;    if ((dayMask & 16) > 0) yield return DayOfWeek.Friday;    if ((dayMask & 32) > 0) yield return DayOfWeek.Saturday;    if ((dayMask & 64) > 0) yield return DayOfWeek.Sunday;}

#20


This one creates array with single element added at the very beginning:

这个创建了一开始就添加了单个元素的数组:

public static T[] Prepend<T>(this T[] array, T item){    T[] result = new T[array.Length + 1];    result[0] = item;    Array.Copy(array, 0, result, 1, array.Length);    return result;}string[] some = new string[] { "foo", "bar" };...some = some.Prepend("baz"); 

And this one helps me when I need to convert some expression to it's square:

当我需要将一些表达式转换为正方形时,这个可以帮助我:

public static double Sq(this double arg){    return arg * arg;}(x - x0).Sq() + (y - y0).Sq() + (z - z0).Sq()

#21


Here's another one I wrote:

这是我写的另一个:

    public static class StringExtensions    {        /// <summary>        /// Returns a Subset string starting at the specified start index and ending and the specified end        /// index.        /// </summary>        /// <param name="s">The string to retrieve the subset from.</param>        /// <param name="startIndex">The specified start index for the subset.</param>        /// <param name="endIndex">The specified end index for the subset.</param>        /// <returns>A Subset string starting at the specified start index and ending and the specified end        /// index.</returns>        public static string Subsetstring(this string s, int startIndex, int endIndex)        {            if (startIndex < 0) throw new ArgumentOutOfRangeException("startIndex", "Must be positive.");            if (endIndex < 0) throw new ArgumentOutOfRangeException("endIndex", "Must be positive.");            if (startIndex > endIndex) throw new ArgumentOutOfRangeException("endIndex", "Must be >= startIndex.");            return s.Substring(startIndex, (endIndex - startIndex));        }        /// <summary>        /// Finds the specified Start Text and the End Text in this string instance, and returns a string        /// containing all the text starting from startText, to the begining of endText. (endText is not        /// included.)        /// </summary>        /// <param name="s">The string to retrieve the subset from.</param>        /// <param name="startText">The Start Text to begin the Subset from.</param>        /// <param name="endText">The End Text to where the Subset goes to.</param>        /// <param name="ignoreCase">Whether or not to ignore case when comparing startText/endText to the string.</param>        /// <returns>A string containing all the text starting from startText, to the begining of endText.</returns>        public static string Subsetstring(this string s, string startText, string endText, bool ignoreCase)        {            if (string.IsNullOrEmpty(startText)) throw new ArgumentNullException("startText", "Must be filled.");            if (string.IsNullOrEmpty(endText)) throw new ArgumentNullException("endText", "Must be filled.");            string temp = s;            if (ignoreCase)            {                temp = s.ToUpperInvariant();                startText = startText.ToUpperInvariant();                endText = endText.ToUpperInvariant();            }            int start = temp.IndexOf(startText);            int end = temp.IndexOf(endText, start);            return Subsetstring(s, start, end);        }    }

The motivation behind this one was simple. It always bugged me how the built in Substring method took startindex and length as it's parameters. It's ALWAYS much more helpful to do startindex and endindex. So, I rolled my own:

这个背后的动机很简单。它始终告诉我内置的Substring方法如何将startindex和length作为参数。使用startindex和endindex总是更有帮助。所以,我自己动手:

Usage:

        string s = "This is a tester for my cool extension method!!";        s = s.Subsetstring("tester", "cool",true);

The reason I had to use Subsetstring was because Substring's overload already takes two ints. If anyone has a better name, please, let me know!!

我必须使用Subsetstring的原因是因为Substring的重载已经需要两个整数。如果有人有更好的名字,请告诉我!

#22


cool, also loving Extensions!

很酷,也很喜欢扩展!

here's a few.

这里有几个。

This one will get the last Date of a Month:

这个将获得一个月的最后一个日期:

<System.Runtime.CompilerServices.Extension()> _    Public Function GetLastMonthDay(ByVal Source As DateTime) As DateTime        Dim CurrentMonth As Integer = Source.Month        Dim MonthCounter As Integer = Source.Month        Dim LastDay As DateTime        Dim DateCounter As DateTime = Source        LastDay = Source        Do While MonthCounter = CurrentMonth            DateCounter = DateCounter.AddDays(1)            MonthCounter = DateCounter.Month            If MonthCounter = CurrentMonth Then                LastDay = DateCounter            End If        Loop        Return LastDay    End Function

these two make reflection a bit easier:

这两个使反射更容易:

 <System.Runtime.CompilerServices.Extension()> _    Public Function GetPropertyValue(Of ValueType)(ByVal Source As Object, ByVal PropertyName As String) As ValueType        Dim pInfo As System.Reflection.PropertyInfo        pInfo = Source.GetType.GetProperty(PropertyName)        If pInfo Is Nothing Then            Throw New Exception("Property " & PropertyName & " does not exists for object of type " & Source.GetType.Name)        Else            Return pInfo.GetValue(Source, Nothing)        End If    End Function    <System.Runtime.CompilerServices.Extension()> _    Public Function GetPropertyType(ByVal Source As Object, ByVal PropertyName As String) As Type        Dim pInfo As System.Reflection.PropertyInfo        pInfo = Source.GetType.GetProperty(PropertyName)        If pInfo Is Nothing Then            Throw New Exception("Property " & PropertyName & " does not exists for object of type " & Source.GetType.Name)        Else            Return pInfo.PropertyType        End If    End Function

#23


The extension methods I use the most would have to be the ones in the System.Linq.Enumerable class.

我最常使用的扩展方法必须是System.Linq.Enumerable类中的扩展方法。

And a good and useful extension to that list you can find in MoreLinq.

您可以在MoreLinq中找到该列表的一个很好且有用的扩展。

#24


There are a couple that I've mentioned here that I use:

我在这里提到了一些我使用的:

  • Easier checking on flags enums

    更容易检查标志枚举

    if( enumVar.IsSet( MyEnum.PossibleFlag ) ) //..then

    if(enumVar.IsSet(MyEnum.PossibleFlag))//..then

  • Inline checking of nulls

    内联检查空值

    myObject.IfNotNull( x => x.Property );

    myObject.IfNotNull(x => x.Property);

#25


few extensions I use mostly. first set is object extensions, really only for converting.

我主要使用的扩展很少。第一组是对象扩展,实际上只用于转换。

public static class ObjectExtension{    public static T As<T>(this object value)    {        return (value != null && value is T) ? (T)value : default(T);    }    public static int AsInt(this string value)    {        if (value.HasValue())        {            int result;            var success = int.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out result);            if (success)            {                return result;            }        }        return 0;    }    public static Guid AsGuid(this string value)    {        return value.HasValue() ? new Guid(value) : Guid.Empty;    }}

string extensions

public static class StringExtension{    public static bool HasValue(this string value)    {        return string.IsNullOrEmpty(value) == false;    }    public static string Slug(this string value)    {        if (value.HasValue())        {            var builder = new StringBuilder();            var slug = value.Trim().ToLower();            foreach (var c in slug)            {                switch (c)                {                    case ' ':                        builder.Append("-");                        break;                    case '&':                        builder.Append("and");                        break;                    default:                        if ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') && c != '-')                        {                            builder.Append(c);                        }                        break;                }            }            return builder.ToString();        }        return string.Empty;    }    public static string Truncate(this string value, int limit)    {        return (value.Length > limit) ? string.Concat(value.Substring(0, Math.Min(value.Length, limit)), "...") : value;    }}

and last is some enum extensions

最后是一些枚举扩展

public static class EnumExtensions{    public static bool Has<T>(this Enum source, params T[] values)    {        var value = Convert.ToInt32(source, CultureInfo.InvariantCulture);        foreach (var i in values)        {            var mask = Convert.ToInt32(i, CultureInfo.InvariantCulture);            if ((value & mask) == 0)            {                return false;            }        }        return true;    }    public static bool Has<T>(this Enum source, T values)    {        var value = Convert.ToInt32(source, CultureInfo.InvariantCulture);        var mask = Convert.ToInt32(values, CultureInfo.InvariantCulture);        return (value & mask) != 0;    }    public static T Add<T>(this Enum source, T v)    {        var value = Convert.ToInt32(source, CultureInfo.InvariantCulture);        var mask = Convert.ToInt32(v, CultureInfo.InvariantCulture);        return Enum.ToObject(typeof(T), value | mask).As<T>();    }    public static T Remove<T>(this Enum source, T v)    {        var value = Convert.ToInt32(source, CultureInfo.InvariantCulture);        var mask = Convert.ToInt32(v, CultureInfo.InvariantCulture);        return Enum.ToObject(typeof(T), value & ~mask).As<T>();    }    public static T AsEnum<T>(this string value)    {        try        {            return Enum.Parse(typeof(T), value, true).As<T>();        }        catch        {            return default(T);        }    }}

#26


With regular use of StringBuilder, you may see the need to combine AppendFormat() and AppendLine().

经常使用StringBuilder,您可能会发现需要组合AppendFormat()和AppendLine()。

public static void AppendFormatLine(this StringBuilder sb, string format, params object[] args){    sb.AppendFormat(format, args);    sb.AppendLine();}

Also, since I'm converting an application from VB6 to C#, the following are very useful to me:

此外,由于我正在将应用程序从VB6转换为C#,以下内容对我非常有用:

public static string Left(this string s, int length){    if (s.Length >= length)        return s.Substring(0, length);    throw new ArgumentException("Length must be less than the length of the string.");}public static string Right(this string s, int length){    if (s.Length >= length)        return s.Substring(s.Length - length, length);    throw new ArgumentException("Length must be less than the length of the string.");}

#27


My favourite from my own personal collection of string utils is one that will parse a strongly typed value from a string for any type that has a TryParse method:

我最喜欢的是我自己的字符串utils集合,它可以解析任何具有TryParse方法的类型的字符串中的强类型值:

public static class StringUtils{    /// <summary>    /// This method will parse a value from a string.    /// If the string is null or not the right format to parse a valid value,    /// it will return the default value provided.    /// </summary>    public static T To<t>(this string value, T defaultValue)        where T: struct    {        var type = typeof(T);        if (value != null)        {            var parse = type.GetMethod("TryParse", new Type[] { typeof(string), type.MakeByRefType() });            var parameters = new object[] { value, default(T) };            if((bool)parse.Invoke(null, parameters))                return (T)parameters[1];        }        return defaultValue;    }    /// <summary>    /// This method will parse a value from a string.    /// If the string is null or not the right format to parse a valid value,    /// it will return the default value for the type.    /// </summary>    public static T To<t>(this string value)        where T : struct    {        return value.To<t>(default(T));    }}

It's great for getting strongly typed information from query strings:

它非常适合从查询字符串中获取强类型信息:

var value = Request.QueryString["value"].To<int>();

#28


I hate having to do this everywhere:

我不想到处都这样做:

DataSet ds = dataLayer.GetSomeData(1, 2, 3);if(ds != null){    if(ds.Tables.Count > 0){        DataTable dt = ds.Tables[0];        foreach(DataRow dr in dt.Rows){            //Do some processing        }    }}

Instead I usually use the following Extension Method:

相反,我通常使用以下扩展方法:

public static IEnumerable<DataRow> DataRows(this DataSet current){    if(current != null){        if(current.Tables.Count > 0){            DataTable dt = current.Tables[0];            foreach(DataRow dr in dt.Rows){                yield return dr;            }        }    }}

So the first example then becomes:

那么第一个例子就变成了:

foreach(DataRow row in ds.DataRows()){    //Do some processing}

Yay, Extension Methods!

耶,扩展方法!

#29


String.format should not have been static. So I use an extension method called frmt:

String.format不应该是静态的。所以我使用一个名为frmt的扩展方法:

<Extension()> Public Function frmt(ByVal format As String,                                   ByVal ParamArray args() As Object) As String    If format Is Nothing Then Throw New ArgumentNullException("format")    Return String.Format(format, args)End Function

When I want to read or write a number to a byte stream without constructing a binary writer (technically you aren't supposed to modify the raw stream after you've wrapped it with a writer):

当我想在没有构建二进制编写器的情况下读取或写入字节流的数字时(从技术上讲,在用编写器包装后不应该修改原始流):

<Extension()> Public Function Bytes(ByVal n As ULong,                                    ByVal byteOrder As ByteOrder,                                    Optional ByVal size As Integer = 8) As Byte()    Dim data As New List(Of Byte)    Do Until data.Count >= size        data.Add(CByte(n And CULng(&HFF)))        n >>= 8    Loop    Select Case byteOrder        Case ByteOrder.BigEndian            Return data.ToArray.reversed        Case ByteOrder.LittleEndian            Return data.ToArray        Case Else            Throw New ArgumentException("Unrecognized byte order.")    End SelectEnd Function<Extension()> Public Function ToULong(ByVal data As IEnumerable(Of Byte),                                      ByVal byteOrder As ByteOrder) As ULong    If data Is Nothing Then Throw New ArgumentNullException("data")    Dim val As ULong    Select Case byteOrder        Case ByteOrder.LittleEndian            data = data.Reverse        Case ByteOrder.BigEndian            'no change required        Case Else            Throw New ArgumentException("Unrecognized byte order.")    End Select    For Each b In data        val <<= 8        val = val Or b    Next b    Return valEnd Function

#30


This one shifts a sequence so that you get the given item first. I used it for example to take the day of weeks and shift it so that the first day in the sequence is the first day of the week for the current culture.

这个移动一个序列,以便您首先获得给定的项目。例如,我用它来取几周的时间并将其移动,以便序列中的第一天是当前文化的一周的第一天。

    /// <summary>    /// Shifts a sequence so that the given <paramref name="item"/> becomes the first.     /// Uses the specified equality <paramref name="comparer"/> to find the item.    /// </summary>    /// <typeparam name="TSource">Type of elements in <paramref name="source"/>.</typeparam>    /// <param name="source">Sequence of elements.</param>    /// <param name="item">Item which will become the first.</param>    /// <param name="comparer">Used to find the first item.</param>    /// <returns>A shifted sequence. For example Shift({1,2,3,4,5,6}, 3) would become {3,4,5,6,1,2}. </returns>    public static IEnumerable<TSource> Shift<TSource>(this IEnumerable<TSource> source, TSource item, IEqualityComparer<TSource> comparer)    {        var queue = new Queue<TSource>();        bool found = false;        foreach (TSource e in source)        {            if (!found && comparer.Equals(item, e))                found = true;            if (found)                yield return e;            else                queue.Enqueue(e);        }        while (queue.Count > 0)            yield return queue.Dequeue();    }    /// <summary>    /// Shifts a sequence so that the given item becomes the first.     /// Uses the default equality comparer to find the item.    /// </summary>    /// <typeparam name="TSource">Type of elements in <paramref name="source"/>.</typeparam>    /// <param name="source">Sequence of elements.</param>    /// <param name="element">Element which will become the first.</param>    /// <returns>A shifted sequence. For example Shift({1,2,3,4,5,6}, 3) would become {3,4,5,6,1,2}. </returns>    public static IEnumerable<TSource> Shift<TSource>(this IEnumerable<TSource> source, TSource element)    {        return Shift(source, element, EqualityComparer<TSource>.Default);    }