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

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

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


当前回答

这是我今天刚创建的一个。

// requires .NET 4

public static TReturn NullOr<TIn, TReturn>(this TIn obj, Func<TIn, TReturn> func,
        TReturn elseValue = default(TReturn)) where TIn : class
    { return obj != null ? func(obj) : elseValue; }

// versions for CLR 2, which doesn't support optional params

public static TReturn NullOr<TIn, TReturn>(this TIn obj, Func<TIn, TReturn> func,
        TReturn elseValue) where TIn : class
    { return obj != null ? func(obj) : elseValue; }
public static TReturn NullOr<TIn, TReturn>(this TIn obj, Func<TIn, TReturn> func)
        where TIn : class
    { return obj != null ? func(obj) : default(TReturn); }

它让你这样做:

var lname = thingy.NullOr(t => t.Name).NullOr(n => n.ToLower());

哪个比这个更流畅,(依我看)更容易阅读:

var lname = (thingy != null ? thingy.Name : null) != null
    ? thingy.Name.ToLower() : null;

其他回答

下面是我用来减少提取单个属性的一些方法:

public static T GetAttribute<T>(this ICustomAttributeProvider provider, bool inherit = false, int index = 0) where T : Attribute
{
    return provider.GetAttribute(typeof(T), inherit, index) as T;
}

public static Attribute GetAttribute(this ICustomAttributeProvider provider, Type type, bool inherit = false, int index = 0)
{
    bool exists = provider.IsDefined(type, inherit);
    if (!exists)
    {
        return null;
    }

    object[] attributes = provider.GetCustomAttributes(type, inherit);
    if (attributes != null && attributes.Length != 0)
    {
        return attributes[index] as Attribute;
    }
    else
    {
        return null;
    }
}

用法(枚举描述hack的实现):

public static string GetDescription(this Enum value)
{
    var fieldInfo = value.GetType().GetField(value.ToString());
    var attribute = fieldInfo.GetAttribute<DescriptionAttribute>();
    return attribute != null ? attribute.Description : null;
}

请随意将其包含在CodePlex项目中!

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

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

        task.Start();

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

愚蠢的示例:

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

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

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

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

……怎么样?

public static bool IsWinXPOrHigher(this OperatingSystem OS)
{
  return (OS.Platform == PlatformID.Win32NT)
    && ((OS.Version.Major > 5) || ((OS.Version.Major == 5) && (OS.Version.Minor >= 1)));
}

public static bool IsWinVistaOrHigher(this OperatingSystem OS)
{
  return (OS.Platform == PlatformID.Win32NT)
    && (OS.Version.Major >= 6);
}

public static bool IsWin7OrHigher(this OperatingSystem OS)
{
  return (OS.Platform == PlatformID.Win32NT)
    && ((OS.Version.Major > 6) || ((OS.Version.Major == 6) && (OS.Version.Minor >= 1)));
}

public static bool IsWin8OrHigher(this OperatingSystem OS)
{
  return (OS.Platform == PlatformID.Win32NT)
    && ((OS.Version.Major > 6) || ((OS.Version.Major == 6) && (OS.Version.Minor >= 2)));
}

用法:

if (Environment.OSVersion.IsWinXPOrHigher())
{
  // do stuff
}

if (Environment.OSVersion.IsWinVistaOrHigher())
{
  // do stuff
}

if (Environment.OSVersion.IsWin7OrHigher())
{
  // do stuff
}

if (Environment.OSVersion.IsWin8OrHigher())
{
  // do stuff
}

如果你有波斯语,并且必须用波斯语向用户显示数字:

static public string ToFaString         (this string value)
        {
            // 1728 , 1584
            string result = "";
            if (value != null)
            {
                char[] resChar = value.ToCharArray();
                for (int i = 0; i < resChar.Length; i++)
                {
                    if (resChar[i] >= '0' && resChar[i] <= '9')
                        result += (char)(resChar[i] + 1728);
                    else
                        result += resChar[i];
                }
            }
            return result;
        }

用于winforms填充组合框:

List<MyObject> myObjects = new List<MyObject>() { 
    new MyObject() {Name = "a", Id = 0}, 
    new MyObject() {Name = "b", Id = 1}, 
    new MyObject() {Name = "c", Id = 2} }
comboBox.FillDataSource<MyObject>(myObjects, x => x.Name);

扩展方法:

/** <summary>Fills the System.Windows.Forms.ComboBox object DataSource with a 
 * list of T objects.</summary>
 * <param name="values">The list of T objects.</param>
 * <param name="displayedValue">A function to apply to each element to get the 
 * display value.</param>
 */
public static void FillDataSource<T>(this ComboBox comboBox, List<T> values,
    Func<T, String> displayedValue) {

    // Create dataTable
    DataTable data = new DataTable();
    data.Columns.Add("ValueMember", typeof(T));
    data.Columns.Add("DisplayMember");

    for (int i = 0; i < values.Count; i++) {
        // For each value/displayed value

        // Create new row with value & displayed value
        DataRow dr = data.NewRow();
        dr["ValueMember"] = values[i];
        dr["DisplayMember"] = displayedValue(values[i]) ?? "";
        // Add row to the dataTable
        data.Rows.Add(dr);
    }

    // Bind datasource to the comboBox
    comboBox.DataSource = data;
    comboBox.ValueMember = "ValueMember";
    comboBox.DisplayMember = "DisplayMember";
}