首页 文章

你最喜欢的C#扩展方法是什么? (codeplex.com/extensionoverflow)

提问于
浏览
478

让我们列出你发布优秀和最喜欢的extension methods的答案 .

要求是必须发布完整代码以及如何使用它的示例和说明 .

基于对该主题的高度关注,我在Codeplex上设置了一个名为extensionoverflow的开源项目 .

Please mark your answers with an acceptance to put the code in the Codeplex project.

Please post the full sourcecode and not a link.

Codeplex News:

24.08.2010 Codeplex页面现在在这里:http://extensionoverflow.codeplex.com/

11.11.2008 XmlSerialize / XmlDeserialize 现在是ImplementedUnit Tested .

11.11.2008仍有更多开发人员的空间 . ;-) Join NOW!

11.11.2008第三个贡献者加入ExtensionOverflow,欢迎来到BKristensen

11.11.2008 FormatWith 现在是ImplementedUnit Tested .

09.11.2008第二个贡献者加入ExtensionOverflow . 欢迎来到chakrit .

09.11.2008我们需要更多开发人员 . ;-)

09.11.2008 ThrowIfArgumentIsNull 现在ImplementedUnit Tested在Codeplex上 .

30 回答

  • 14

    处理尺寸的便捷方式:

    public static class Extensions {
        public static int K(this int value) {
            return value * 1024;
        }
        public static int M(this int value) {
            return value * 1024 * 1024;
        }
    }
    
    public class Program {
        public void Main() {
            WSHttpContextBinding serviceMultipleTokenBinding = new WSHttpContextBinding() {
                MaxBufferPoolSize = 2.M(), // instead of 2097152
                MaxReceivedMessageSize = 64.K(), // instead of 65536
            };
        }
    }
    
  • 15
    public static bool In<T>(this T source, params T[] list)
    {
      if(null==source) throw new ArgumentNullException("source");
      return list.Contains(source);
    }
    

    允许我替换:

    if(reallyLongIntegerVariableName == 1 || 
        reallyLongIntegerVariableName == 6 || 
        reallyLongIntegerVariableName == 9 || 
        reallyLongIntegerVariableName == 11)
    {
      // do something....
    }
    
    and
    
    if(reallyLongStringVariableName == "string1" || 
        reallyLongStringVariableName == "string2" || 
        reallyLongStringVariableName == "string3")
    {
      // do something....
    }
    
    and
    
    if(reallyLongMethodParameterName == SomeEnum.Value1 || 
        reallyLongMethodParameterName == SomeEnum.Value2 || 
        reallyLongMethodParameterName == SomeEnum.Value3 || 
        reallyLongMethodParameterName == SomeEnum.Value4)
    {
      // do something....
    }
    

    附:

    if(reallyLongIntegerVariableName.In(1,6,9,11))
    {
          // do something....
    }
    
    and
    
    if(reallyLongStringVariableName.In("string1","string2","string3"))
    {
          // do something....
    }
    
    and
    
    if(reallyLongMethodParameterName.In(SomeEnum.Value1, SomeEnum.Value2, SomeEnum.Value3, SomeEnum.Value4)
    {
      // do something....
    }
    
  • 25

    我的MiscUtil项目中有各种扩展方法(那里有完整的源代码 - 我不打算在这里重复它) . 我的最爱,其中一些涉及其他类(如范围):

    日期和时间 - 主要用于单元测试 . 不确定我是否会在制作中使用它们:)

    var birthday = 19.June(1976);
    var workingDay = 7.Hours() + 30.Minutes();
    

    范围和踩踏 - 非常感谢Marc Gravell为他的operator stuff做出这样的决定:

    var evenNaturals = 2.To(int.MaxValue).Step(2);
    var daysSinceBirth = birthday.To(DateTime.Today).Step(1.Days());
    

    比较:

    var myComparer = ProjectionComparer.Create(Person p => p.Name);
    var next = myComparer.ThenBy(p => p.Age);
    var reversed = myComparer.Reverse();
    

    参数检查:

    x.ThrowIfNull("x");
    

    LINQ to XML应用于匿名类型(或具有适当属性的其他类型):

    // <Name>Jon</Name><Age>32</Age>
    new { Name="Jon", Age=32}.ToXElements();
    // Name="Jon" Age="32" (as XAttributes, obviously)
    new { Name="Jon", Age=32}.ToXAttributes()
    

    推LINQ - 在这里解释需要很长时间,但要搜索它 .

  • 32

    string.Format快捷方式:

    public static class StringExtensions
    {
        // Enable quick and more natural string.Format calls
        public static string F(this string s, params object[] args)
        {
            return string.Format(s, args);
        }
    }
    

    例:

    var s = "The co-ordinate is ({0}, {1})".F(point.X, point.Y);
    

    要快速复制粘贴,请转到here .

    你不觉得输入 "some string".F("param") 而不是 string.Format("some string", "param") 更自然吗?

    要获得更易读的名称,请尝试以下建议之一:

    s = "Hello {0} world {1}!".Fmt("Stack", "Overflow");
    s = "Hello {0} world {1}!".FormatBy("Stack", "Overflow");
    s = "Hello {0} world {1}!".FormatWith("Stack", "Overflow");
    s = "Hello {0} world {1}!".Display("Stack", "Overflow");
    s = "Hello {0} world {1}!".With("Stack", "Overflow");
    

    ..

  • 12

    这些有用吗?

    public static bool CoinToss(this Random rng)
    {
        return rng.Next(2) == 0;
    }
    
    public static T OneOf<T>(this Random rng, params T[] things)
    {
        return things[rng.Next(things.Length)];
    }
    
    Random rand;
    bool luckyDay = rand.CoinToss();
    string babyName = rand.OneOf("John", "George", "Radio XBR74 ROCKS!");
    
  • 23
    public static class ComparableExtensions
    {
      public static bool Between<T>(this T actual, T lower, T upper) where T : IComparable<T>
      {
        return actual.CompareTo(lower) >= 0 && actual.CompareTo(upper) < 0;
      }
    }
    

    例:

    if (myNumber.Between(3,7))
    {
      // ....
    }
    
  • 147

    扩展方法:

    public static void AddRange<T, S>(this ICollection<T> list, params S[] values)
        where S : T
    {
        foreach (S value in values)
            list.Add(value);
    }
    

    该方法适用于所有类型,并允许您将一系列项目作为参数添加到列表中 .

    例:

    var list = new List<Int32>();
    list.AddRange(5, 4, 8, 4, 2);
    
  • 29

    一定要把它放在codeplex项目中 .

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

    /// <summary>Serializes an object of type T in to an xml string</summary>
    /// <typeparam name="T">Any class type</typeparam>
    /// <param name="obj">Object to serialize</param>
    /// <returns>A string that represents Xml, empty otherwise</returns>
    public static string XmlSerialize<T>(this T obj) where T : class, new()
    {
        if (obj == null) throw new ArgumentNullException("obj");
    
        var serializer = new XmlSerializer(typeof(T));
        using (var writer = new StringWriter())
        {
            serializer.Serialize(writer, obj);
            return writer.ToString();
        }
    }
    
    /// <summary>Deserializes an xml string in to an object of Type T</summary>
    /// <typeparam name="T">Any class type</typeparam>
    /// <param name="xml">Xml as string to deserialize from</param>
    /// <returns>A new object of type T is successful, null if failed</returns>
    public static T XmlDeserialize<T>(this string xml) where T : class, new()
    {
        if (xml == null) throw new ArgumentNullException("xml");
    
        var serializer = new XmlSerializer(typeof(T));
        using (var reader = new StringReader(xml))
        {
            try { return (T)serializer.Deserialize(reader); }
            catch { return null; } // Could not be deserialized to this type.
        }
    }
    
  • 16

    ForEach for IEnumerables

    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只允许您为每个项执行某些操作而无需任何转换/数据操作 .

    我做了这个,所以我可以用更实用的风格编程,我很惊讶List有一个ForEach而IEnumerable没有 .

    把它放在codeplex项目中

  • 38

    我的转换扩展程序允许您执行以下操作:

    int i = myString.To<int>();
    

    在这里,as posted on TheSoftwareJedi.com

    public static T To<T>(this IConvertible obj)
    {
      return (T)Convert.ChangeType(obj, typeof(T));
    }
    
    public static T ToOrDefault<T>
                 (this IConvertible obj)
    {
        try
        {
            return To<T>(obj);
        }
        catch
        {
            return default(T);
        }
    }
    
    public static bool ToOrDefault<T>
                        (this IConvertible obj,
                         out T newObj)
    {
        try
        {
            newObj = To<T>(obj); 
            return true;
        }
        catch
        {
            newObj = default(T); 
            return false;
        }
    }
    
    public static T ToOrOther<T>
                           (this IConvertible obj,
                           T other)
    {
      try
      {
          return To<T>obj);
      }
      catch
      {
          return other;
      }
    }
    
    public static bool ToOrOther<T>
                             (this IConvertible obj,
                             out T newObj,
                             T other)
    {
        try
        {
            newObj = To<T>(obj);
            return true;
        }
        catch
        {
            newObj = other;
            return false;
        }
    }
    
    public static T ToOrNull<T>
                          (this IConvertible obj)
                          where T : class
    {
        try
        {
            return To<T>(obj);
        }
        catch
        {
            return null;
        }
    }
    
    public static bool ToOrNull<T>
                      (this IConvertible obj,
                      out T newObj)
                      where T : class
    {
        try
        {
            newObj = To<T>(obj);
            return true;
        }
        catch
        {
            newObj = null;
            return false;
        }
    }
    

    您可以在失败时请求默认值(调用空白构造函数或“0”表示数字),指定“默认”值(我称之为“其他”),或者请求null(其中T:class) . 我还提供了两个静默异常模型,以及一个典型的TryParse模型,它返回一个指示所采取操作的bool,一个out参数保存新值 . 所以我们的代码可以做这样的事情

    int i = myString.To<int>();
    string a = myInt.ToOrDefault<string>();
    //note type inference
    DateTime d = myString.ToOrOther(DateTime.MAX_VALUE);
    double d;
    //note type inference
    bool didItGiveDefault = myString.ToOrDefault(out d);
    string s = myDateTime.ToOrNull<string>();
    

    我无法让Nullable类型非常干净地滚动到整个事物中 . 在我扔掉毛巾之前,我试了大约20分钟 .

  • 55

    我有一个用于记录异常的扩展方法:

    public static void Log(this Exception obj)
    {
      //your logging logic here
    }
    

    它像这样使用:

    try
    {
        //Your stuff here
    }
    catch(Exception ex)
    {
        ex.Log();
    }
    

    [抱歉发布两次;第二个更好的设计:-)]

  • 31
    public static class StringExtensions {
    
        /// <summary>
        /// Parses a string into an Enum
        /// </summary>
        /// <typeparam name="T">The type of the Enum</typeparam>
        /// <param name="value">String value to parse</param>
        /// <returns>The Enum corresponding to the stringExtensions</returns>
        public static T EnumParse<T>(this string value) {
            return StringExtensions.EnumParse<T>(value, false);
        }
    
        public static T EnumParse<T>(this string value, bool ignorecase) {
    
            if (value == null) {
                throw new ArgumentNullException("value");
            }
    
            value = value.Trim();
    
            if (value.Length == 0) {
                throw new ArgumentException("Must specify valid information for parsing in the string.", "value");
            }
    
            Type t = typeof(T);
    
            if (!t.IsEnum) {
                throw new ArgumentException("Type provided must be an Enum.", "T");
            }
    
            return (T)Enum.Parse(t, value, ignorecase);
        }
    }
    

    用于将字符串解析为枚举 .

    public enum TestEnum
    {
        Bar,
        Test
    }
    
    public class Test
    {
        public void Test()
        {
            TestEnum foo = "Test".EnumParse<TestEnum>();
        }
     }
    

    信用到Scott Dorman

    ---编辑Codeplex项目---

    我问Scott Dorman是否会介意我们在Codeplex项目中发布他的代码 . 这是我从他那里得到的答复:

    感谢SO帖子和CodePlex项目的单挑 . 我对这个问题提出了答案 . 是的,该代码实际上属于CodeProject Open License(http://www.codeproject.com/info/cpol10.aspx)下的公共域 . 我在CodePlex项目中包含它没有任何问题,如果你想将我添加到项目中(用户名是sdorman),我将添加该方法以及一些额外的枚举助手方法 .

  • 160

    我发现这个非常有用:

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

    您可以在CodePlex上使用它 .

  • 76

    DateTimeExtensions

    例子:

    DateTime firstDayOfMonth = DateTime.Now.First();
    DateTime lastdayOfMonth = DateTime.Now.Last();
    DateTime lastFridayInMonth = DateTime.Now.Last(DayOfWeek.Friday);
    DateTime nextFriday = DateTime.Now.Next(DayOfWeek.Friday);
    DateTime lunchTime = DateTime.Now.SetTime(11, 30);
    DateTime noonOnFriday = DateTime.Now.Next(DayOfWeek.Friday).Noon();
    DateTime secondMondayOfMonth = DateTime.Now.First(DayOfWeek.Monday).Next(DayOfWeek.Monday).Midnight();
    
  • 58

    gitorious.org/cadenza是我见过的一些最有用的扩展方法的完整库 .

  • 89

    这是我经常用于演示文稿格式的一个 .

    public static string ToTitleCase(this string mText)
    {
        if (mText == null) return mText;
    
        System.Globalization.CultureInfo cultureInfo = System.Threading.Thread.CurrentThread.CurrentCulture;
        System.Globalization.TextInfo textInfo = cultureInfo.TextInfo;
    
        // TextInfo.ToTitleCase only operates on the string if is all lower case, otherwise it returns the string unchanged.
        return textInfo.ToTitleCase(mText.ToLower());
    }
    
  • 28

    这是罗马数字的来往 . 不经常使用,但可能很方便 . 用法:

    if ("IV".IsValidRomanNumeral())
    {
       // Do useful stuff with the number 4.
    }
    
    Console.WriteLine("MMMDCCCLXXXVIII".ParseRomanNumeral());
    Console.WriteLine(3888.ToRomanNumeralString());
    

    来源:

    public static class RomanNumeralExtensions
        {
            private const int NumberOfRomanNumeralMaps = 13;
    
            private static readonly Dictionary<string, int> romanNumerals =
                new Dictionary<string, int>(NumberOfRomanNumeralMaps)
                {
                    { "M", 1000 }, 
                    { "CM", 900 }, 
                    { "D", 500 }, 
                    { "CD", 400 }, 
                    { "C", 100 }, 
                    { "XC", 90 }, 
                    { "L", 50 }, 
                    { "XL", 40 }, 
                    { "X", 10 }, 
                    { "IX", 9 }, 
                    { "V", 5 }, 
                    { "IV", 4 }, 
                    { "I", 1 }
                };
    
            private static readonly Regex validRomanNumeral = new Regex(
                "^(?i:(?=[MDCLXVI])((M{0,3})((C[DM])|(D?C{0,3}))"
                + "?((X[LC])|(L?XX{0,2})|L)?((I[VX])|(V?(II{0,2}))|V)?))$", 
                RegexOptions.Compiled);
    
            public static bool IsValidRomanNumeral(this string value)
            {
                return validRomanNumeral.IsMatch(value);
            }
    
            public static int ParseRomanNumeral(this string value)
            {
                if (value == null)
                {
                    throw new ArgumentNullException("value");
                }
    
                value = value.ToUpperInvariant().Trim();
    
                var length = value.Length;
    
                if ((length == 0) || !value.IsValidRomanNumeral())
                {
                    throw new ArgumentException("Empty or invalid Roman numeral string.", "value");
                }
    
                var total = 0;
                var i = length;
    
                while (i > 0)
                {
                    var digit = romanNumerals[value[--i].ToString()];
    
                    if (i > 0)
                    {
                        var previousDigit = romanNumerals[value[i - 1].ToString()];
    
                        if (previousDigit < digit)
                        {
                            digit -= previousDigit;
                            i--;
                        }
                    }
    
                    total += digit;
                }
    
                return total;
            }
    
            public static string ToRomanNumeralString(this int value)
            {
                const int MinValue = 1;
                const int MaxValue = 3999;
    
                if ((value < MinValue) || (value > MaxValue))
                {
                    throw new ArgumentOutOfRangeException("value", value, "Argument out of Roman numeral range.");
                }
    
                const int MaxRomanNumeralLength = 15;
                var sb = new StringBuilder(MaxRomanNumeralLength);
    
                foreach (var pair in romanNumerals)
                {
                    while (value / pair.Value > 0)
                    {
                        sb.Append(pair.Key);
                        value -= pair.Value;
                    }
                }
    
                return sb.ToString();
            }
        }
    
  • 43

    对于Winform控件:

    /// <summary>
    /// Returns whether the function is being executed during design time in Visual Studio.
    /// </summary>
    public static bool IsDesignTime(this Control control)
    {
        if (LicenseManager.UsageMode == LicenseUsageMode.Designtime)
        {
            return true;
        }
    
        if (control.Site != null && control.Site.DesignMode)
        {
            return true;
        }
    
        var parent = control.Parent;
        while (parent != null)
        {
            if (parent.Site != null && parent.Site.DesignMode)
            {
                return true;
            }
            parent = parent.Parent;
        }
        return false;
    }
    
    /// <summary>
    /// Sets the DropDownWidth to ensure that no item's text is cut off.
    /// </summary>
    public static void SetDropDownWidth(this ComboBox comboBox)
    {
        var g = comboBox.CreateGraphics();
        var font = comboBox.Font;
        float maxWidth = 0;
    
        foreach (var item in comboBox.Items)
        {
            maxWidth = Math.Max(maxWidth, g.MeasureString(item.ToString(), font).Width);
        }
    
        if (comboBox.Items.Count > comboBox.MaxDropDownItems)
        {
            maxWidth += SystemInformation.VerticalScrollBarWidth;
        }
    
        comboBox.DropDownWidth = Math.Max(comboBox.Width, Convert.ToInt32(maxWidth));
    }
    

    IsDesignTime用法:

    public class SomeForm : Form
    {
        public SomeForm()
        {
            InitializeComponent();
    
            if (this.IsDesignTime())
            {
                return;
            }
    
            // Do something that makes the visual studio crash or hang if we're in design time,
            // but any other time executes just fine
        }
    }
    

    SetDropdownWidth用法:

    ComboBox cbo = new ComboBox { Width = 50 };
    cbo.Items.Add("Short");
    cbo.Items.Add("A little longer");
    cbo.Items.Add("Holy cow, this is a really, really long item. How in the world will it fit?");
    cbo.SetDropDownWidth();
    

    我忘了提及,随意在Codeplex上使用这些...

  • 46

    ThrowIfArgumentIsNull是一个很好的方法来做我们都应该做的空检查做 .

    public static class Extensions
    {
        public static void ThrowIfArgumentIsNull<T>(this T obj, string parameterName) where T : class
        {
            if (obj == null) throw new ArgumentNullException(parameterName + " not allowed to be null");
        }
    }
    

    下面是使用它的方法,它适用于命名空间中的所有类或在其中使用命名空间的任何位置 .

    internal class Test
    {
        public Test(string input1)
        {
            input1.ThrowIfArgumentIsNull("input1");
        }
    }
    

    It's ok to use this code on the CodePlex project.

  • 18

    移动到C#时我想念Visual Basic's With statement,所以这里是:

    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项目

  • 14

    采用camelCaseWord或PascalCaseWord并将其“字形化”,即camelCaseWord => camel Case Word

    public static string Wordify( this string camelCaseWord )
    {
        // if the word is all upper, just return it
        if( !Regex.IsMatch( camelCaseWord, "[a-z]" ) )
            return camelCaseWord;
    
        return string.Join( " ", Regex.Split( camelCaseWord, @"(?<!^)(?=[A-Z])" ) );
    }
    

    我经常将它与Capitalize结合使用

    public static string Capitalize( this string word )
    {
        return word[0].ToString( ).ToUpper( ) + word.Substring( 1 );
    }
    

    用法示例

    SomeEntityObject entity = DataAccessObject.GetSomeEntityObject( id );
    List<PropertyInfo> properties = entity.GetType().GetPublicNonCollectionProperties( );
    
    // wordify the property names to act as column headers for an html table or something
    List<string> columns = properties.Select( p => p.Name.Capitalize( ).Wordify( ) ).ToList( );
    

    Free to use in codeplex project

  • 43

    我觉得这个很有帮助

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

    它删除了调用代码中的空检查 . 你现在可以做

    MyList.EmptyIfNull().Where(....)
    
  • 13

    将double转换为使用指定区域性格式化的字符串:

    public static class ExtensionMethods 
    {
      public static string ToCurrency(this double value, string cultureName)
      {
        CultureInfo currentCulture = new CultureInfo(cultureName);
        return (string.Format(currentCulture, "{0:C}", value));
      }
    }
    

    例:

    double test = 154.20;
    string testString = test.ToCurrency("en-US"); // $154.20
    
  • 28

    下面是一个extension method,它适应Rick Strahl's code(以及注释),以阻止您每次将其转换为字符串时猜测或读取字节数组或文本文件的字节顺序标记 .

    该片段允许您简单地执行以下操作:

    byte[] buffer = File.ReadAllBytes(@"C:\file.txt");
    string content = buffer.GetString();
    

    如果您发现任何错误,请添加评论 . 随意将其包含在Codeplex项目中 .

    public static class Extensions
    {
        /// <summary>
        /// Converts a byte array to a string, using its byte order mark to convert it to the right encoding.
        /// Original article: http://www.west-wind.com/WebLog/posts/197245.aspx
        /// </summary>
        /// <param name="buffer">An array of bytes to convert</param>
        /// <returns>The byte as a string.</returns>
        public static string GetString(this byte[] buffer)
        {
            if (buffer == null || buffer.Length == 0)
                return "";
    
            // Ansi as default
            Encoding encoding = Encoding.Default;       
    
            /*
                EF BB BF    UTF-8 
                FF FE UTF-16    little endian 
                FE FF UTF-16    big endian 
                FF FE 00 00 UTF-32, little endian 
                00 00 FE FF UTF-32, big-endian 
             */
    
            if (buffer[0] == 0xef && buffer[1] == 0xbb && buffer[2] == 0xbf)
                encoding = Encoding.UTF8;
            else if (buffer[0] == 0xfe && buffer[1] == 0xff)
                encoding = Encoding.Unicode;
            else if (buffer[0] == 0xfe && buffer[1] == 0xff)
                encoding = Encoding.BigEndianUnicode; // utf-16be
            else if (buffer[0] == 0 && buffer[1] == 0 && buffer[2] == 0xfe && buffer[3] == 0xff)
                encoding = Encoding.UTF32;
            else if (buffer[0] == 0x2b && buffer[1] == 0x2f && buffer[2] == 0x76)
                encoding = Encoding.UTF7;
    
            using (MemoryStream stream = new MemoryStream())
            {
                stream.Write(buffer, 0, buffer.Length);
                stream.Seek(0, SeekOrigin.Begin);
                using (StreamReader reader = new StreamReader(stream, encoding))
                {
                    return reader.ReadToEnd();
                }
            }
        }
    }
    
  • 24

    这是我刚刚创建的一个 .

    // 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());
    

    哪个更流畅,(IMO)比这更容易阅读:

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

    “请在接受将代码放入Codeplex项目时标记您的答案 . ”

    为什么?这个网站上的所有东西都在CC-by-sa-2.5之下,所以只需将你的扩展溢出项目置于相同的许可下,你就可以自由使用它了 .

    无论如何,这是一个String.Reverse函数,基于this question .

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

    在从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一起使用 .


    对于如何做到这一点,我们都有一些好的评论,而且我有机会在不同的上下文中实现类似的东西,所以这是另一个版本:

    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);
    }
    
  • 232

    令我恼火的是,LINQ给了我一个OrderBy,它接受一个实现IComparer作为参数的类,但不支持传入一个简单的匿名比较器函数 . 我纠正了这一点 .

    这个类从比较器函数创建一个IComparer ...

    /// <summary>
    ///     Creates an <see cref="IComparer{T}"/> instance for the given
    ///     delegate function.
    /// </summary>
    internal class ComparerFactory<T> : IComparer<T>
    {
        public static IComparer<T> Create(Func<T, T, int> comparison)
        {
            return new ComparerFactory<T>(comparison);
        }
    
        private readonly Func<T, T, int> _comparison;
    
        private ComparerFactory(Func<T, T, int> comparison)
        {
            _comparison = comparison;
        }
    
        #region IComparer<T> Members
    
        public int Compare(T x, T y)
        {
            return _comparison(x, y);
        }
    
        #endregion
    }
    

    ...并且这些扩展方法在枚举上公开了我的新OrderBy重载 . 我怀疑它适用于LINQ to SQL,但它对于LINQ to Objects非常有用 .

    public static class EnumerableExtensions
    {
        /// <summary>
        /// Sorts the elements of a sequence in ascending order by using a specified comparison delegate.
        /// </summary>
        public static IOrderedEnumerable<TSource> OrderBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector,
                                                                         Func<TKey, TKey, int> comparison)
        {
            var comparer = ComparerFactory<TKey>.Create(comparison);
            return source.OrderBy(keySelector, comparer);
        }
    
        /// <summary>
        /// Sorts the elements of a sequence in descending order by using a specified comparison delegate.
        /// </summary>
        public static IOrderedEnumerable<TSource> OrderByDescending<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector,
                                                                                   Func<TKey, TKey, int> comparison)
        {
            var comparer = ComparerFactory<TKey>.Create(comparison);
            return source.OrderByDescending(keySelector, comparer);
        }
    }
    

    如果你愿意,欢迎你把它放在codeplex上 .

  • 14

    这个适用于MVC,它增加了为每个 ViewPage 中可用的 Html 变量生成 <label /> 标记的功能 . 希望它会对尝试开发类似扩展的其他人有用 .

    Use:

    <%= Html.Label("LabelId", "ForId", "Text")%>
    

    Output:

    <label id="LabelId" for="ForId">Text</label>
    

    Code:

    public static class HtmlHelperExtensions
    {
        public static string Label(this HtmlHelper Html, string @for, string text)
        {
            return Html.Label(null, @for, text);
        }
    
        public static string Label(this HtmlHelper Html, string @for, string text, object htmlAttributes)
        {
            return Html.Label(null, @for, text, htmlAttributes);
        }
    
        public static string Label(this HtmlHelper Html, string @for, string text, IDictionary<string, object> htmlAttributes)
        {
            return Html.Label(null, @for, text, htmlAttributes);
        }
    
        public static string Label(this HtmlHelper Html, string id, string @for, string text)
        {
            return Html.Label(id, @for, text, null);
        }
    
        public static string Label(this HtmlHelper Html, string id, string @for, string text, object htmlAttributes)
        {
            return Html.Label(id, @for, text, new RouteValueDictionary(htmlAttributes));
        }
    
        public static string Label(this HtmlHelper Html, string id, string @for, string text, IDictionary<string, object> htmlAttributes)
        {
            TagBuilder tag = new TagBuilder("label");
    
            tag.MergeAttributes(htmlAttributes);
    
            if (!string.IsNullOrEmpty(id))
                tag.MergeAttribute("id", Html.AttributeEncode(id));
    
            tag.MergeAttribute("for", Html.AttributeEncode(@for));
    
            tag.SetInnerText(Html.Encode(text));
    
            return tag.ToString(TagRenderMode.Normal);
        }
    }
    
  • 17

    转过来:

    DbCommand command = connection.CreateCommand();
    command.CommandText = "SELECT @param";
    
    DbParameter param = command.CreateParameter();
    param.ParameterName = "@param";
    param.Value = "Hello World";
    
    command.Parameters.Add(param);
    

    ......进入这个:

    DbCommand command = connection.CreateCommand("SELECT {0}", "Hello World");
    

    ...使用此扩展方法:

    using System;
    using System.Data.Common;
    using System.Globalization;
    using System.Reflection;
    
    namespace DbExtensions {
    
       public static class Db {
    
          static readonly Func<DbConnection, DbProviderFactory> getDbProviderFactory;
          static readonly Func<DbCommandBuilder, int, string> getParameterName;
          static readonly Func<DbCommandBuilder, int, string> getParameterPlaceholder;
    
          static Db() {
    
             getDbProviderFactory = (Func<DbConnection, DbProviderFactory>)Delegate.CreateDelegate(typeof(Func<DbConnection, DbProviderFactory>), typeof(DbConnection).GetProperty("DbProviderFactory", BindingFlags.Instance | BindingFlags.NonPublic).GetGetMethod(true));
             getParameterName = (Func<DbCommandBuilder, int, string>)Delegate.CreateDelegate(typeof(Func<DbCommandBuilder, int, string>), typeof(DbCommandBuilder).GetMethod("GetParameterName", BindingFlags.Instance | BindingFlags.NonPublic, Type.DefaultBinder, new Type[] { typeof(Int32) }, null));
             getParameterPlaceholder = (Func<DbCommandBuilder, int, string>)Delegate.CreateDelegate(typeof(Func<DbCommandBuilder, int, string>), typeof(DbCommandBuilder).GetMethod("GetParameterPlaceholder", BindingFlags.Instance | BindingFlags.NonPublic, Type.DefaultBinder, new Type[] { typeof(Int32) }, null));
          }
    
          public static DbProviderFactory GetProviderFactory(this DbConnection connection) {
             return getDbProviderFactory(connection);
          }
    
          public static DbCommand CreateCommand(this DbConnection connection, string commandText, params object[] parameters) {
    
             if (connection == null) throw new ArgumentNullException("connection");
    
             return CreateCommandImpl(GetProviderFactory(connection).CreateCommandBuilder(), connection.CreateCommand(), commandText, parameters);
          }
    
          private static DbCommand CreateCommandImpl(DbCommandBuilder commandBuilder, DbCommand command, string commandText, params object[] parameters) {
    
             if (commandBuilder == null) throw new ArgumentNullException("commandBuilder");
             if (command == null) throw new ArgumentNullException("command");
             if (commandText == null) throw new ArgumentNullException("commandText");
    
             if (parameters == null || parameters.Length == 0) {
                command.CommandText = commandText;
                return command;
             }
    
             object[] paramPlaceholders = new object[parameters.Length];
    
             for (int i = 0; i < paramPlaceholders.Length; i++) {
    
                DbParameter dbParam = command.CreateParameter();
                dbParam.ParameterName = getParameterName(commandBuilder, i);
                dbParam.Value = parameters[i] ?? DBNull.Value;
                command.Parameters.Add(dbParam);
    
                paramPlaceholders[i] = getParameterPlaceholder(commandBuilder, i);
             }
    
             command.CommandText = String.Format(CultureInfo.InvariantCulture, commandText, paramPlaceholders);
    
             return command;
          }
       }
    }
    

    更多ADO.NET扩展方法:DbExtensions

相关问题