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

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

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


当前回答

当我迁移到c#时,我错过了Visual Basic的With语句,所以它是这样的:

public static void With<T>(this T obj, Action<T> act) { act(obj); }

下面是如何在c#中使用它:

someVeryVeryLonggggVariableName.With(x => {
    x.Int = 123;
    x.Str = "Hello";
    x.Str2 = " World!";
});

节省了大量的输入!

将其与:

someVeryVeryLonggggVariableName.Int = 123;
someVeryVeryLonggggVariableName.Str = "Hello";
someVeryVeryLonggggVariableName.Str2 = " World!";

加入codeplex项目

其他回答

The Substring method on the string class has always felt inadequate to me. Usually when you do a substring, you know the character(s) from where you want to start, and the charachter(s) where you want to end. Thus, I've always felt that have to specify length as the second parameter is stupid. Therefore, I've written my own extension methods. One that takes a startIndex and an endIndex. And one, that takes a startText (string) and endText (string) so you can just specify the text from where to start the substring, and the text for where to end it.

注意:我不能将方法命名为。net中的Substring,因为我的第一个重载采用了与。net重载中的一个相同的参数类型。因此我将它们命名为Subsetstring。请随意添加到CodePlex…

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 > endIndex)
        {
            throw new InvalidOperationException("End Index must be after Start Index.");
        }

        if (startIndex < 0)
        {
            throw new InvalidOperationException("Start Index must be a positive number.");
        }

        if(endIndex <0)
        {
            throw new InvalidOperationException("End Index must be a positive number.");
        }

        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) || string.IsNullOrEmpty(endText))
        {
            throw new ArgumentException("Start Text and End Text cannot be empty.");
        }
        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);
    }
}

用法:

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

输出:"test for my "

我厌倦了乏味的空检查,而拉值从MySqlDataReader,所以:

public static DateTime? GetNullableDateTime(this MySqlDataReader dr, string fieldName)
{
    DateTime? nullDate = null;
    return dr.IsDBNull(dr.GetOrdinal(fieldName)) ? nullDate : dr.GetDateTime(fieldName);
}

public static string GetNullableString(this MySqlDataReader dr, string fieldName)
{
    return dr.IsDBNull(dr.GetOrdinal(fieldName)) ? String.Empty : dr.GetString(fieldName);
}

public static char? GetNullableChar(this MySqlDataReader dr, string fieldName)
{
    char? nullChar = null;
    return dr.IsDBNull(dr.GetOrdinal(fieldName)) ? nullChar : dr.GetChar(fieldName);
}

当然,这可以用于任何SqlDataReader。


hangy和Joe都对如何做到这一点提出了一些很好的意见,我也有机会在不同的环境中实现类似的东西,所以这里是另一个版本:

public static int? GetNullableInt32(this IDataRecord dr, int ordinal)
{
    int? nullInt = null;
    return dr.IsDBNull(ordinal) ? nullInt : dr.GetInt32(ordinal);
}

public static int? GetNullableInt32(this IDataRecord dr, string fieldname)
{
    int ordinal = dr.GetOrdinal(fieldname);
    return dr.GetNullableInt32(ordinal);
}

public static bool? GetNullableBoolean(this IDataRecord dr, int ordinal)
{
    bool? nullBool = null;
    return dr.IsDBNull(ordinal) ? nullBool : dr.GetBoolean(ordinal);
}

public static bool? GetNullableBoolean(this IDataRecord dr, string fieldname)
{
    int ordinal = dr.GetOrdinal(fieldname);
    return dr.GetNullableBoolean(ordinal);
}

我在所有项目中用到的两个小技巧(有些人会觉得很傻)是:

public static bool IsNull(this object o){
  return o == null;
}

and

public static bool IsNullOrEmpty(this string s){
  return string.IsNullOrEmpty(s);
}

它使我的代码更流畅。

if (myClassInstance.IsNull()) //... do something

if (myString.IsNullOrEmpty()) //... do something

我认为这些是很好的扩展属性;如果我们能得到这些。

用于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项目中

在单元测试中很有用:

public static IList<T> Clone<T>(this IList<T> list) where T : ICloneable
{
    var ret = new List<T>(list.Count);
    foreach (var item in list)
        ret.Add((T)item.Clone());

    // done
    return ret;
}

像TWith2Sugars这样的一系列,交替缩短语法:

public static long? ToNullableInt64(this string val)
{
    long ret;
    return Int64.TryParse(val, out ret) ? ret : new long?();
}

最后,在BCL中是否已经有一些东西做了下面的事情?

public static void Split<T>(this T[] array, 
    Func<T,bool> determinator, 
    IList<T> onTrue, 
    IList<T> onFalse)
{
    if (onTrue == null)
        onTrue = new List<T>();
    else
        onTrue.Clear();

    if (onFalse == null)
        onFalse = new List<T>();
    else
        onFalse.Clear();

    if (determinator == null)
        return;

    foreach (var item in array)
    {
        if (determinator(item))
            onTrue.Add(item);
        else
            onFalse.Add(item);
    }
}